Skip to content

Commit 79f8a0a

Browse files
authored
Merge pull request #32 from rameel/master
GetShortAssemblyQualifiedName revisited
2 parents e3f5f71 + 4cd1cce commit 79f8a0a

File tree

2 files changed

+186
-41
lines changed

2 files changed

+186
-41
lines changed

Main/src/Reflection/ReflectionExtensions.cs

Lines changed: 108 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,114 @@ public static bool IsDebugAssembly([NotNull] this Assembly assembly)
4646
public static string GetShortAssemblyQualifiedName([NotNull] this Type type)
4747
{
4848
Code.NotNull(type, nameof(type));
49-
return type + ", " + type.Assembly.GetName().Name;
49+
50+
void WriteAssemblyName(StringBuilder sb, Type t)
51+
{
52+
sb.Append(", ");
53+
54+
var index = -1;
55+
var assemblyFullName = t.Assembly.FullName;
56+
57+
while (true)
58+
{
59+
index = assemblyFullName.IndexOf(',', index + 1);
60+
DebugCode.BugIf(index == 0, "Invalid assembly name");
61+
62+
if (index < 0)
63+
{
64+
sb.Append(assemblyFullName);
65+
return;
66+
}
67+
68+
if (assemblyFullName[index - 1] != '\\')
69+
{
70+
sb.Append(assemblyFullName, 0, index);
71+
return;
72+
}
73+
}
74+
}
75+
76+
void WriteGenericArguments(StringBuilder sb, Type t)
77+
{
78+
DebugCode.AssertState(t.IsGenericType && !t.IsGenericTypeDefinition, "Invalid type");
79+
80+
sb.Append('[');
81+
82+
var arguments = t.GetGenericArguments();
83+
for (var i = 0; i < arguments.Length; i++)
84+
{
85+
if (i != 0)
86+
sb.Append(',');
87+
88+
sb.Append('[');
89+
WriteFull(sb, arguments[i]);
90+
sb.Append(']');
91+
}
92+
93+
sb.Append(']');
94+
}
95+
96+
void WriteElementType(StringBuilder sb, Type t)
97+
{
98+
DebugCode.AssertState(t.IsArray || t.IsPointer || t.IsByRef, "Invalid type");
99+
100+
Write(sb, t.GetElementType());
101+
102+
if (t.IsArray)
103+
{
104+
sb.Append('[');
105+
sb.Append(',', t.GetArrayRank() - 1);
106+
sb.Append(']');
107+
}
108+
else
109+
{
110+
sb.Append(t.IsPointer ? '*' : '&');
111+
}
112+
}
113+
114+
void WriteType(StringBuilder sb, Type t)
115+
{
116+
if (t.DeclaringType != null)
117+
{
118+
WriteType(sb, t.DeclaringType);
119+
sb.Append('+');
120+
}
121+
122+
sb.Append(t.Name);
123+
}
124+
125+
void Write(StringBuilder sb, Type t)
126+
{
127+
if (t.IsGenericType && !t.IsGenericTypeDefinition)
128+
{
129+
WriteType(sb, t);
130+
WriteGenericArguments(sb, t);
131+
}
132+
else if (t.IsArray || t.IsPointer || t.IsByRef)
133+
{
134+
WriteElementType(sb, t);
135+
}
136+
else
137+
{
138+
WriteType(sb, t);
139+
}
140+
}
141+
142+
void WriteFull(StringBuilder sb, Type t)
143+
{
144+
if (t.Namespace.NotNullNorEmpty())
145+
{
146+
sb.Append(t.Namespace);
147+
sb.Append('.');
148+
}
149+
150+
Write(sb, t);
151+
WriteAssemblyName(sb, t);
152+
}
153+
154+
var builder = new StringBuilder();
155+
WriteFull(builder, type);
156+
return builder.ToString();
50157
}
51158

52159
/// <summary>

Main/tests/Reflection/ReflectionExtensionsTest.cs

Lines changed: 78 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections;
33
using System.Collections.Generic;
44
using System.Collections.ObjectModel;
5+
using System.Diagnostics.CodeAnalysis;
56
using System.Runtime.CompilerServices;
67
using System.Text.RegularExpressions;
78

@@ -14,15 +15,15 @@ public partial class ReflectionExtensionsTest
1415
{
1516
private static object[] _source =
1617
{
17-
new object[] {typeof(List<int>), "System.Collections.Generic.List`1[System.Int32], mscorlib"},
18-
new object[] {typeof(List<>), "System.Collections.Generic.List`1[T], mscorlib"},
19-
new object[] {typeof(IList<int>), "System.Collections.Generic.IList`1[System.Int32], mscorlib"},
20-
new object[] {typeof(Dictionary<,>), "System.Collections.Generic.Dictionary`2[TKey,TValue], mscorlib"},
21-
new object[] {typeof(Dictionary<int, string>), "System.Collections.Generic.Dictionary`2[System.Int32,System.String], mscorlib"},
22-
new object[] {typeof(Dictionary<int, List<int>>), "System.Collections.Generic.Dictionary`2[System.Int32,System.Collections.Generic.List`1[System.Int32]], mscorlib"},
18+
new object[] {typeof(List<int>), "System.Collections.Generic.List`1[[System.Int32, mscorlib]], mscorlib"},
19+
new object[] {typeof(List<>), "System.Collections.Generic.List`1, mscorlib"},
20+
new object[] {typeof(IList<int>), "System.Collections.Generic.IList`1[[System.Int32, mscorlib]], mscorlib"},
21+
new object[] {typeof(Dictionary<,>), "System.Collections.Generic.Dictionary`2, mscorlib"},
22+
new object[] {typeof(Dictionary<int, string>), "System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[System.String, mscorlib]], mscorlib"},
23+
new object[] {typeof(Dictionary<int, List<int>>), "System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[System.Collections.Generic.List`1[[System.Int32, mscorlib]], mscorlib]], mscorlib"},
2324
new object[] {typeof(int), "System.Int32, mscorlib"},
24-
new object[] {typeof(int?), "System.Nullable`1[System.Int32], mscorlib"},
25-
new object[] {typeof(KeyValuePair<int, string>?), "System.Nullable`1[System.Collections.Generic.KeyValuePair`2[System.Int32,System.String]], mscorlib"},
25+
new object[] {typeof(int?), "System.Nullable`1[[System.Int32, mscorlib]], mscorlib"},
26+
new object[] {typeof(KeyValuePair<int, string>?), "System.Nullable`1[[System.Collections.Generic.KeyValuePair`2[[System.Int32, mscorlib],[System.String, mscorlib]], mscorlib]], mscorlib"},
2627
new object[] {typeof(int[]), "System.Int32[], mscorlib"},
2728
new object[] {typeof(int[,]), "System.Int32[,], mscorlib"},
2829
new object[] {typeof(int[,][]), "System.Int32[][,], mscorlib"},
@@ -33,21 +34,21 @@ public partial class ReflectionExtensionsTest
3334
new object[] {typeof(int[,][,,][]), "System.Int32[][,,][,], mscorlib"},
3435
new object[] {typeof(int[][,,][,]), "System.Int32[,][,,][], mscorlib"},
3536
new object[] {typeof(int[,][,,][,]), "System.Int32[,][,,][,], mscorlib"},
36-
new object[] {typeof(int?[]), "System.Nullable`1[System.Int32][], mscorlib"},
37-
new object[] {typeof(int?[,]), "System.Nullable`1[System.Int32][,], mscorlib"},
38-
new object[] {typeof(int?[,][]), "System.Nullable`1[System.Int32][][,], mscorlib"},
39-
new object[] {typeof(int?[][,]), "System.Nullable`1[System.Int32][,][], mscorlib"},
40-
new object[] {typeof(int?[][]), "System.Nullable`1[System.Int32][][], mscorlib"},
41-
new object[] {typeof(int?[][][]), "System.Nullable`1[System.Int32][][][], mscorlib"},
42-
new object[] {typeof(int?[][,,][]), "System.Nullable`1[System.Int32][][,,][], mscorlib"},
43-
new object[] {typeof(int?[,][,,][]), "System.Nullable`1[System.Int32][][,,][,], mscorlib"},
44-
new object[] {typeof(int?[][,,][,]), "System.Nullable`1[System.Int32][,][,,][], mscorlib"},
45-
new object[] {typeof(int?[,][,,][,]), "System.Nullable`1[System.Int32][,][,,][,], mscorlib"},
46-
new object[] {typeof(List<int?>), "System.Collections.Generic.List`1[System.Nullable`1[System.Int32]], mscorlib"},
47-
new object[] {typeof(List<int?[]>), "System.Collections.Generic.List`1[System.Nullable`1[System.Int32][]], mscorlib"},
48-
new object[] {typeof(List<int?[,,]>), "System.Collections.Generic.List`1[System.Nullable`1[System.Int32][,,]], mscorlib"},
49-
new object[] {typeof(List<int?[][,,]>), "System.Collections.Generic.List`1[System.Nullable`1[System.Int32][,,][]], mscorlib"},
50-
new object[] {typeof(List<int?[,][]>), "System.Collections.Generic.List`1[System.Nullable`1[System.Int32][][,]], mscorlib"},
37+
new object[] {typeof(int?[]), "System.Nullable`1[[System.Int32, mscorlib]][], mscorlib"},
38+
new object[] {typeof(int?[,]), "System.Nullable`1[[System.Int32, mscorlib]][,], mscorlib"},
39+
new object[] {typeof(int?[,][]), "System.Nullable`1[[System.Int32, mscorlib]][][,], mscorlib"},
40+
new object[] {typeof(int?[][,]), "System.Nullable`1[[System.Int32, mscorlib]][,][], mscorlib"},
41+
new object[] {typeof(int?[][]), "System.Nullable`1[[System.Int32, mscorlib]][][], mscorlib"},
42+
new object[] {typeof(int?[][][]), "System.Nullable`1[[System.Int32, mscorlib]][][][], mscorlib"},
43+
new object[] {typeof(int?[][,,][]), "System.Nullable`1[[System.Int32, mscorlib]][][,,][], mscorlib"},
44+
new object[] {typeof(int?[,][,,][]), "System.Nullable`1[[System.Int32, mscorlib]][][,,][,], mscorlib"},
45+
new object[] {typeof(int?[][,,][,]), "System.Nullable`1[[System.Int32, mscorlib]][,][,,][], mscorlib"},
46+
new object[] {typeof(int?[,][,,][,]), "System.Nullable`1[[System.Int32, mscorlib]][,][,,][,], mscorlib"},
47+
new object[] {typeof(List<int?>), "System.Collections.Generic.List`1[[System.Nullable`1[[System.Int32, mscorlib]], mscorlib]], mscorlib"},
48+
new object[] {typeof(List<int?[]>), "System.Collections.Generic.List`1[[System.Nullable`1[[System.Int32, mscorlib]][], mscorlib]], mscorlib"},
49+
new object[] {typeof(List<int?[,,]>), "System.Collections.Generic.List`1[[System.Nullable`1[[System.Int32, mscorlib]][,,], mscorlib]], mscorlib"},
50+
new object[] {typeof(List<int?[][,,]>), "System.Collections.Generic.List`1[[System.Nullable`1[[System.Int32, mscorlib]][,,][], mscorlib]], mscorlib"},
51+
new object[] {typeof(List<int?[,][]>), "System.Collections.Generic.List`1[[System.Nullable`1[[System.Int32, mscorlib]][][,], mscorlib]], mscorlib"},
5152
new object[] {typeof(ReflectionExtensions), "CodeJam.Reflection.ReflectionExtensions, CodeJam"},
5253
new object[] {typeof(int).MakePointerType(), "System.Int32*, mscorlib"},
5354
new object[] {typeof(int).MakePointerType().MakeArrayType(), "System.Int32*[], mscorlib"},
@@ -58,18 +59,34 @@ public partial class ReflectionExtensionsTest
5859
new object[] {typeof(int).MakeByRefType(), "System.Int32&, mscorlib"},
5960
new object[] {typeof(int[]).MakeByRefType(), "System.Int32[]&, mscorlib"},
6061
new object[] {typeof(int[][,][,,]).MakeByRefType(), "System.Int32[,,][,][]&, mscorlib"},
61-
new object[] {typeof(int?[]).MakeByRefType(), "System.Nullable`1[System.Int32][]&, mscorlib"},
62-
new object[] {typeof(int?[][,]).MakeByRefType(), "System.Nullable`1[System.Int32][,][]&, mscorlib"},
63-
new object[] {typeof(int?[,][]).MakeByRefType(), "System.Nullable`1[System.Int32][][,]&, mscorlib"},
64-
new object[] {typeof(int?[,][][,,]).MakeByRefType(), "System.Nullable`1[System.Int32][,,][][,]&, mscorlib"},
65-
new object[] {typeof(int?[,][][,,]).MakePointerType(), "System.Nullable`1[System.Int32][,,][][,]*, mscorlib"},
66-
new object[] {typeof(int?).MakePointerType(), "System.Nullable`1[System.Int32]*, mscorlib"},
67-
new object[] {typeof(int?).MakePointerType().MakeByRefType(), "System.Nullable`1[System.Int32]*&, mscorlib"},
68-
new object[] {typeof(int?).MakePointerType().MakePointerType().MakeByRefType(), "System.Nullable`1[System.Int32]**&, mscorlib"},
69-
new object[] {typeof(int?).MakeByRefType(), "System.Nullable`1[System.Int32]&, mscorlib"},
70-
new object[] {typeof(int?).MakePointerType().MakeArrayType(), "System.Nullable`1[System.Int32]*[], mscorlib"},
71-
new object[] {typeof(int?).MakePointerType().MakeArrayType().MakeArrayType(2), "System.Nullable`1[System.Int32]*[][,], mscorlib"},
72-
new object[] {typeof(int?).MakePointerType().MakeArrayType().MakeArrayType(2).MakeByRefType(), "System.Nullable`1[System.Int32]*[][,]&, mscorlib"},
62+
new object[] {typeof(int?[]).MakeByRefType(), "System.Nullable`1[[System.Int32, mscorlib]][]&, mscorlib"},
63+
new object[] {typeof(int?[][,]).MakeByRefType(), "System.Nullable`1[[System.Int32, mscorlib]][,][]&, mscorlib"},
64+
new object[] {typeof(int?[,][]).MakeByRefType(), "System.Nullable`1[[System.Int32, mscorlib]][][,]&, mscorlib"},
65+
new object[] {typeof(int?[,][][,,]).MakeByRefType(), "System.Nullable`1[[System.Int32, mscorlib]][,,][][,]&, mscorlib"},
66+
new object[] {typeof(int?[,][][,,]).MakePointerType(), "System.Nullable`1[[System.Int32, mscorlib]][,,][][,]*, mscorlib"},
67+
new object[] {typeof(int?).MakePointerType(), "System.Nullable`1[[System.Int32, mscorlib]]*, mscorlib"},
68+
new object[] {typeof(int?).MakePointerType().MakeByRefType(), "System.Nullable`1[[System.Int32, mscorlib]]*&, mscorlib"},
69+
new object[] {typeof(int?).MakePointerType().MakePointerType().MakeByRefType(), "System.Nullable`1[[System.Int32, mscorlib]]**&, mscorlib"},
70+
new object[] {typeof(int?).MakeByRefType(), "System.Nullable`1[[System.Int32, mscorlib]]&, mscorlib"},
71+
new object[] {typeof(int?).MakePointerType().MakeArrayType(), "System.Nullable`1[[System.Int32, mscorlib]]*[], mscorlib"},
72+
new object[] {typeof(int?).MakePointerType().MakeArrayType().MakeArrayType(2), "System.Nullable`1[[System.Int32, mscorlib]]*[][,], mscorlib"},
73+
new object[] {typeof(int?).MakePointerType().MakeArrayType().MakeArrayType(2).MakeByRefType(), "System.Nullable`1[[System.Int32, mscorlib]]*[][,]&, mscorlib"},
74+
new object[] {typeof(A), "CodeJam.Reflection.ReflectionExtensionsTest+A, CodeJam-Tests"},
75+
new object[] {typeof(A.B), "CodeJam.Reflection.ReflectionExtensionsTest+A+B, CodeJam-Tests"},
76+
new object[] {typeof(A.B.C), "CodeJam.Reflection.ReflectionExtensionsTest+A+B+C, CodeJam-Tests"},
77+
new object[] {typeof(A<int>), "CodeJam.Reflection.ReflectionExtensionsTest+A`1[[System.Int32, mscorlib]], CodeJam-Tests"},
78+
new object[] {typeof(A<int>.B), "CodeJam.Reflection.ReflectionExtensionsTest+A`1+B[[System.Int32, mscorlib]], CodeJam-Tests"},
79+
new object[] {typeof(A<int>.B.C<int>), "CodeJam.Reflection.ReflectionExtensionsTest+A`1+B+C`1[[System.Int32, mscorlib],[System.Int32, mscorlib]], CodeJam-Tests"},
80+
new object[] {typeof(A<int>.B.C<int?>), "CodeJam.Reflection.ReflectionExtensionsTest+A`1+B+C`1[[System.Int32, mscorlib],[System.Nullable`1[[System.Int32, mscorlib]], mscorlib]], CodeJam-Tests"},
81+
new object[] {typeof(A<int?>.B.C<int?>), "CodeJam.Reflection.ReflectionExtensionsTest+A`1+B+C`1[[System.Nullable`1[[System.Int32, mscorlib]], mscorlib],[System.Nullable`1[[System.Int32, mscorlib]], mscorlib]], CodeJam-Tests"},
82+
new object[] {typeof(A<int?[]>.B.C<int?>), "CodeJam.Reflection.ReflectionExtensionsTest+A`1+B+C`1[[System.Nullable`1[[System.Int32, mscorlib]][], mscorlib],[System.Nullable`1[[System.Int32, mscorlib]], mscorlib]], CodeJam-Tests"},
83+
new object[] {typeof(A<int?[]>.B.C<int?>[]), "CodeJam.Reflection.ReflectionExtensionsTest+A`1+B+C`1[[System.Nullable`1[[System.Int32, mscorlib]][], mscorlib],[System.Nullable`1[[System.Int32, mscorlib]], mscorlib]][], CodeJam-Tests"},
84+
new object[] {typeof(A<int?[]>.B.C<int?>[]).MakePointerType().MakeByRefType(), "CodeJam.Reflection.ReflectionExtensionsTest+A`1+B+C`1[[System.Nullable`1[[System.Int32, mscorlib]][], mscorlib],[System.Nullable`1[[System.Int32, mscorlib]], mscorlib]][]*&, CodeJam-Tests"},
85+
new object[] {typeof(A<int?[]>.B.C<int?>[]).MakePointerType(), "CodeJam.Reflection.ReflectionExtensionsTest+A`1+B+C`1[[System.Nullable`1[[System.Int32, mscorlib]][], mscorlib],[System.Nullable`1[[System.Int32, mscorlib]], mscorlib]][]*, CodeJam-Tests"},
86+
new object[] {typeof(A<int?[]>.B.C<int?>[]).MakeByRefType(), "CodeJam.Reflection.ReflectionExtensionsTest+A`1+B+C`1[[System.Nullable`1[[System.Int32, mscorlib]][], mscorlib],[System.Nullable`1[[System.Int32, mscorlib]], mscorlib]][]&, CodeJam-Tests"},
87+
new object[] {typeof(A<int?[]>.B.C<A<int?[]>.B.C<int?>[]>[]), "CodeJam.Reflection.ReflectionExtensionsTest+A`1+B+C`1[[System.Nullable`1[[System.Int32, mscorlib]][], mscorlib],[CodeJam.Reflection.ReflectionExtensionsTest+A`1+B+C`1[[System.Nullable`1[[System.Int32, mscorlib]][], mscorlib],[System.Nullable`1[[System.Int32, mscorlib]], mscorlib]][], CodeJam-Tests]][], CodeJam-Tests"},
88+
new object[] {typeof(A<int?[]>.B.C<A<int?[]>.B.C<int?>[]>[]).MakeByRefType(), "CodeJam.Reflection.ReflectionExtensionsTest+A`1+B+C`1[[System.Nullable`1[[System.Int32, mscorlib]][], mscorlib],[CodeJam.Reflection.ReflectionExtensionsTest+A`1+B+C`1[[System.Nullable`1[[System.Int32, mscorlib]][], mscorlib],[System.Nullable`1[[System.Int32, mscorlib]], mscorlib]][], CodeJam-Tests]][]&, CodeJam-Tests"},
89+
new object[] {typeof(WithoutNsTestClass), "WithoutNsTestClass, CodeJam-Tests" }
7390
};
7491

7592
[Test]
@@ -94,11 +111,7 @@ public void GetShortAssemblyQualifiedNameTest(Type type, string expected)
94111
Console.WriteLine("Expected: {0}", regex.Replace(type.AssemblyQualifiedName ?? "", ""));
95112

96113
Assert.AreEqual(expected, qualifiedName);
97-
98-
if (!type.IsGenericTypeDefinition)
99-
{
100-
Assert.AreEqual(type, Type.GetType(qualifiedName));
101-
}
114+
Assert.AreEqual(type, Type.GetType(qualifiedName));
102115
}
103116

104117
[TestCase(typeof(List<int>), typeof(IList<int>), ExpectedResult = true)]
@@ -273,5 +286,30 @@ public TestAnonymousCaseAttribute()
273286
[TestCase(typeof(DateTime?), ExpectedResult = false)]
274287
[TestCase(typeof(DateTime), ExpectedResult = false)]
275288
public bool IsAnonymous(Type type) => type.IsAnonymous();
289+
290+
#region Inner types
291+
private class A
292+
{
293+
public class B
294+
{
295+
public class C
296+
{
297+
}
298+
}
299+
}
300+
301+
[SuppressMessage("ReSharper", "UnusedTypeParameter")]
302+
private class A<TOuter>
303+
{
304+
public class B
305+
{
306+
public class C<TInner>
307+
{
308+
}
309+
}
310+
}
311+
#endregion
276312
}
277313
}
314+
315+
internal class WithoutNsTestClass { }

0 commit comments

Comments
 (0)