While migrating a project from VS2010 to VS2012, I ran into the following problem. The project is using Reflection a lot, and in order to get the MethodInfo from an interface the following code was placed:
Expression<Func<ITest, Func<ServiceRequest, ServiceResponse>>> expression = scv => scv.Get;
UnaryExpression unaryExpression = expression.Body as UnaryExpression;
MethodCallExpression methodCallExpression = unaryExpression.Operand as MethodCallExpression;
ConstantExpression constantExpression = methodCallExpression.Arguments[2] as ConstantExpression;
MethodInfo myMethod = constantExpression.Value as MethodInfo;
This worked fine compiled with VS2010, but the methodCallExpression.Arguments.Count() was 2 if the code is compiled with VS2012 aiming .Net 4.0.
After decompiling, I noticed that the compiler was generating different code for the same expression.
This is a design problem because the design should not relay on "magic numbers" like the number 2 on methodCallExpression.Arguments[2]. I tried to find a solution for this using the following:
MethodCallExpression outermostExpression = expression .Body as MethodCallExpression;
MethodInfo myMethod = outermostExpression.Method;
But outermostExpression is null.
Finally, I made it work changing the expression as follow:
Expression<Func<ITest, ServiceResponse>> expression = scv => scv.Get(default(ServiceRequest));
MethodCallExpression outermostExpression = expression.Body as MethodCallExpression;
Assert.AreEqual("Get", outermostExpression.Method.Name);
It is not ideal, but it works on both VS2010 and VS2012.
Is there a way to find the MethodInfo from an expression like the following:
Expression<Func<ITest, ServiceResponse>> expression = scv => scv.Get(default(ServiceRequest));
MethodInfo methodInfo = GetInnerMethodInfo( expression );
Assert.AreEqual("Get", methodInfo.Name);
I'm not sure why there's a difference in the way the expressions compile. But, if you're looking for the method info of the method in the constant delegate, you can compile the expression with an
ITest
implementation to get at the delegatesMethodInfo
. For example:..where
Test
is some class and implementsITest
. Which works in both 2012 and 2010.I'm unsure how you can get that method info from the expression in 2012 without first compiling it...
UPDATE:
If compiling the expression isn't an option, it appears that the compiler is generating a different expression and putting the
MethodInfo
in theMethodCallExpression.Object
property in the C# 5 compiler. You can check to see if that property is notnull
and use its value for theMethodInfo
, or continue on getting an element in theArguments
collection. For example:I'm using the LINQ query to get at the element in the
Arguments
collection, if you prefer the hard-coded index, you could probably use that instead. More complete error-checking is necessary as well.