The .GetType type does not work when called as a group of methods, but not in a lambda expression

The following example shows that Type.GetType does not work in a specific scenario.

GetType succeeds when I provide it with a class name string (including a namespace) in a lambda expression, but it fails when I specify a GetType call as a group of methods.

Fails:

collectionOfClassNames.Select(GetType) 

succeeds:

 collectionOfClassNames.Select(s => GetType(s)) 

Both methods succeed when the class path includes the assembly name. I suspect this is due to the current context / area, taking into account the IL generated for the above. I see differences in IL, but I still can’t explain the exact reason.

The following is an example that demonstrates the problem.

 using System; using System.Linq; using System.Reflection; namespace GetTypeTest { public class FindMe{} class Program { static void Main(string[] args) { var assemblyName = Assembly.GetExecutingAssembly().FullName; var className = "GetTypeTest.FindMe"; var classAndAssembly = string.Format("{0}, {1}", className, assemblyName); // 1) GetType succeeds when input is "class, assembly", using method group var result = new[] { classAndAssembly }.Select(Type.GetType).ToArray(); Console.WriteLine("1) Method group & class+assembly: {0}", result.First()); // 2) GetType fails when input is just the class name, using method group var result2 = new[] { className }.Select(Type.GetType).ToArray(); Console.WriteLine("2) Method group & class name only: {0}", result2.First()); // 3) Identical to (2) except using lamba expression - this succeeds... var result3 = new[] { className }.Select(s => Type.GetType(s)).ToArray(); Console.WriteLine("3) Lambda expression & class name only: {0}", result3.First()); // 4) Method group and core type class name var result4 = new[] { "System.String" }.Select(Type.GetType).ToArray(); Console.WriteLine("4) Method group for System.String: {0}", result4.First()); Console.ReadLine(); } } } 

I would like to know why # 2 fails, but No. 3 succeeds.

+7
reflection c # lambda
source share
1 answer

Not 100% sure, I could be wrong. . I suggest that I review.

Version 2 compiled into a func delegate like this new Func<string, Type>(Type.GetType)

Version 3 is compiled into a compiler-generated method in the same class, something like this

 [CompilerGenerated] private static Type <Main>b__0(string s) { Type type; type = Type.GetType(s); Label_0009: return type; } 

and to func new Func<string, Type>(Program.<Main>b__0)

So, when executing your Version2 enumerator, it's just func that will be called by my WhereSelectArrayIterator<TSource, TResult> private class lives in System.Core.dll

Where version3 version lives in your build .

We get to the point. If Type.GetType is called with partial names (without a full name), it does not know which assembly is of type, it receives an assembly call and assumes that it lives there.

Therefore, Version3 lives in your assembly. Type.GetType out your assembly type and scans that the assembly fully returns the correct type.

But this does not apply to version 2. You do not actually call Type.GetType there. It is called WhereSelectArrayIterator... class , which is located in System.Core.dll . Thus, it is assumed that your type lives in System.Core.dll and Type.GetType cannot recognize your type.


Edit: The following snippet proves that the statements were correct

We fake the class in our assembly and call it System.Linq.Expressions.Expression to see the behavior.

 namespace GetTypeTest { public class FindMe { } class Program { static void Main(string[] args) { var assemblyName = Assembly.GetExecutingAssembly().FullName; var className = "System.Linq.Expressions.Expression";//"GetTypeTest.FindMe"; var classAndAssembly = string.Format("{0}, {1}", className, assemblyName); // 1) GetType succeeds when input is "class, assembly", using method group var result = new[] { classAndAssembly }.Select(Type.GetType).ToArray(); Console.WriteLine("1) Method group & class+assembly: {0}, {1}", result.First(), result.First().Assembly);//your assembly // 2) GetType fails when input is just the class name, using method group var result2 = new[] { className }.Select(Type.GetType).ToArray(); Console.WriteLine("2) Method group & class name only: {0}, {1}", result2.First(), result2.First().Assembly);//System.Core assembly // 3) Identical to (2) except using lamba expression - this succeeds... var result3 = new[] { className }.Select(s => Type.GetType(s)).ToArray(); Console.WriteLine("3) Lambda expression & class name only: {0}, {1}", result3.First(), result3.First().Assembly);//your assembly // 4) Method group and core type class name var result4 = new[] { "System.String" }.Select(Type.GetType).ToArray(); Console.WriteLine("4) Method group for System.String: {0}, {1}", result4.First(), result4.First().Assembly);//mscorlib assembly Console.ReadLine(); } } } namespace System.Linq.Expressions { public class Expression { } } 

Outputs

 System.Linq.Expressions.Expression [your assembly] System.Linq.Expressions.Expression [System.Core assembly] since WhereSelectArrayIterator.. belongs to System.Core assembly System.Linq.Expressions.Expression [your assembly] since compiler generated method belongs to your assembly System.Linq.Expressions.Expression [mscorlib assembly] 

Hope this helps

+3
source share

All Articles