パフォーマンスが鍵であれば、CreateDelegate
の方が良いと思います。事前にメソッドのシグネチャを知っているので、PropertyInfo
のGetGetMethod
とGetSetMethod
だけです。デリゲートを作成して、同じシグネチャで直接メソッドを実行することができます。式は代理人にいくつかのロジック(メソッドハンドルを持たないロジック)を構築する必要がある場合に適しています。私はこの問題に異なる経路上のいくつかのベンチマークをした約10000000コール用
Func<S, T> Getter;
Action<S, T> Setter;
PropertyInfo Property;
public void Initialize(Expression<Func<S, T>> propertySelector)
{
var body = propertySelector.Body as MemberExpression;
if (body == null)
throw new MissingMemberException("something went wrong");
Property = body.Member as PropertyInfo;
//approaches:
//Getter = s => (T)Property.GetValue(s, null);
//Getter = memberSelector.Compile();
//ParameterExpression inst = Expression.Parameter(typeof(S));
//Getter = Expression.Lambda<Func<S, T>>(Expression.Property(inst, Property), inst).Compile();
//var inst = Expression.Parameter(typeof(S));
//Getter = Expression.Lambda<Func<S, T>>(Expression.Call(inst, Property.GetGetMethod()), inst).Compile();
//Getter = (Func<S, T>)Delegate.CreateDelegate(typeof(Func<S, T>), Property.GetGetMethod());
//Setter = (s, t) => Property.SetValue(s, t, null);
//var val = Expression.Parameter(typeof(T));
//var inst = Expression.Parameter(typeof(S));
//Setter = Expression.Lambda<Action<S, T>>(Expression.Call(inst, Property.GetSetMethod(), val),
// inst, val).Compile();
//Setter = (Action<S, T>)Delegate.CreateDelegate(typeof(Action<S, T>), Property.GetSetMethod());
}
//Actual calls (tested under loop):
public T Get(S instance)
{
//direct invocation:
//return (T)Property.GetValue(instance, null);
//calling the delegate:
//return Getter(instance);
}
public void Set(S instance, T value)
{
//direct invocation:
//Property.SetValue(instance, value, null);
//calling the delegate:
//Setter(instance, value);
}
結果 - (取得、セット):
GetValueメソッド-のSetValue(ダイレクト):3800ミリ、5500ミリ秒
GetValueメソッド-のSetValue(代理人):3600ミリ、5300ミリ秒
コンパイル表現:
Get: Expression.Property: 280 ms
Expression.Call: 280 ms
direct compile: 280 ms
Set: 300 ms
デリゲートを作成:130ミリ、135ミリ秒
直接プロパティコール:私は、あなたのケースでは、書くと70ミリ、70ミリ秒
:
public static Func<S, T> BuildGetAccessor<S, T>(Expression<Func<S, T>> propertySelector)
{
return propertySelector.GetPropertyInfo().GetGetMethod().CreateDelegate<Func<S, T>>();
}
public static Action<S, T> BuildSetAccessor<S, T>(Expression<Func<S, T>> propertySelector)
{
return propertySelector.GetPropertyInfo().GetSetMethod().CreateDelegate<Action<S, T>>();
}
// a generic extension for CreateDelegate
public static T CreateDelegate<T>(this MethodInfo method) where T : class
{
return Delegate.CreateDelegate(typeof(T), method) as T;
}
public static PropertyInfo GetPropertyInfo<S, T>(this Expression<Func<S, T>> propertySelector)
{
var body = propertySelector.Body as MemberExpression;
if (body == null)
throw new MissingMemberException("something went wrong");
return body.Member as PropertyInfo;
}
だから今をあなたは電話します:
TestClass cwp = new TestClass();
var access = BuildGetAccessor((TestClass t) => t.AnyValue);
var result = access(cwp);
ね??正確なことを処理するために汎用クラスhereを書いていました。
"私のアプリケーションの構造上、" < T > "というメソッドを使用することができないので、私はそうしています - あなたのNETFXバージョン<2.0?アプリケーションでジェネリックを使用できないのはなぜですか? –
また、あなたのプロパティのデリゲートを作成することはリフレクションと関係があり、リフレクションを使ってどのような問題を解決しようとしていますか? –
代理人は、パフォーマンスが大幅に向上し、動的に使用することができます。動的呼び出しを使用する必要がある場合は、これらのオプションが優先されます。 – GregRos