以下のメソッドを使用して、非スタティックなMethodInfo
を呼び出すことができるコンパイル済みの式(Func
)に変換します。MethodInfoから作成した式ツリーの明示的な変換
これはうまくいきます:参照オブジェクトと値型の両方を期待するメソッドで呼び出すことができます。
double
が必要なパラメータを持つメソッドを呼び出してint
を渡すメソッドとは異なり、このコンパイル済みの式はそれをサポートせず、InvalidCastException
をスローします。
これを変更して、通常のメソッド呼び出しで発生する同じタイプの暗黙的キャストをサポートするにはどうすればよいですか?
ボーナスに関する質問:instanceExpでまたはReflectedType
をMethodInfo
から使用する必要がありますか?
public Func<object, object[], object> Create(MethodInfo methodInfo)
{
var methodParams = methodInfo.GetParameters();
var arrayParameter = Expression.Parameter(typeof(object[]), "array");
var arguments =
methodParams.Select((p, i) => Expression.Convert(
Expression.ArrayAccess(arrayParameter, Expression.Constant(i)), p.ParameterType))
.Cast<Expression>()
.ToList();
var instanceParameter = Expression.Parameter(typeof(object), "controller");
var instanceExp = Expression.Convert(instanceParameter, methodInfo.DeclaringType);
var callExpression = Expression.Call(instanceExp, methodInfo, arguments);
var bodyExpression = Expression.Convert(callExpression, typeof(object));
return Expression.Lambda<Func<object, object[], object>>(
bodyExpression, instanceParameter, arrayParameter)
.Compile();
}
--- EDIT
ワーキング溶液である:
var changeTypeMethod = typeof(Convert).GetMethod("ChangeType", new Type[] { typeof(object), typeof(TypeCode) });
var arguments =
methodParams.Select((p, i) =>
!typeof(IConvertible).IsAssignableFrom(p.ParameterType)
// If NOT IConvertible, don't try to convert it
? (Expression)Expression.Convert(
Expression.ArrayAccess(arrayParameter, Expression.Constant(i)), p.ParameterType)
:
// Otherwise add an explicit conversion to the correct type to handle int <--> double etc.
(Expression)Expression.Convert(
Expression.Call(changeTypeMethod,
Expression.ArrayAccess(arrayParameter, Expression.Constant(i)),
Expression.Constant(Type.GetTypeCode(p.ParameterType))),
p.ParameterType)
)
.ToList();
OKですが、後で 'Func'が評価されるまで、' int'が 'object'パラメータの中で囲まれていることを知らないとどうしますか?オブジェクトからそれ自身の型に変換し、それを呼び出しのために必要なパラメータ型に変換するためにパラメータをラップするのに必要な魔法の表現は何ですか? –
@IanMercer私はそれを認識したので、過去の私のプロジェクトで覚えている戦略を使って答えを更新しました。 – dasblinkenlight
私はそれを変更してみましたが、まだInvalidCastExceptionがあります。投稿できるコードをお持ちですか? –