プロジェクトをVS2010からVS2012に移行しているときに、次の問題が発生しました。プロジェクトはReflectionを頻繁に使用しており、インターフェイスからMethodInfoを取得するために、次のコードが配置されました。
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;
これはVS2010でコンパイルすると正常に機能しましたが、コードが.Net 4.0を目指してVS2012でコンパイルされた場合、methodCallExpression.Arguments.Count()は2でした。
逆コンパイルした後、コンパイラが同じ式に対して異なるコードを生成していることに気付きました。
これは設計上の問題です。これは、methodCallExpression.Arguments[2]の番号2のような「マジックナンバー」を設計が中継してはならないためです。私は以下を使用してこれの解決策を見つけようとしました:
MethodCallExpression outermostExpression = expression .Body as MethodCallExpression;
MethodInfo myMethod = outermostExpression.Method;
ただし、outermostExpressionはnullです。
最後に、次のように式を変更して動作させました。
Expression<Func<ITest, ServiceResponse>> expression = scv => scv.Get(default(ServiceRequest));
MethodCallExpression outermostExpression = expression.Body as MethodCallExpression;
Assert.AreEqual("Get", outermostExpression.Method.Name);
理想的ではありませんが、VS2010とVS2012の両方で機能します。
次のような式からMethodInfoを見つける方法はありますか?
Expression<Func<ITest, ServiceResponse>> expression = scv => scv.Get(default(ServiceRequest));
MethodInfo methodInfo = GetInnerMethodInfo( expression );
Assert.AreEqual("Get", methodInfo.Name);