2012-05-30 8 views
21

リフレクションの使用にパフォーマンス上の問題があります。
は、だから、私は、オブジェクトのプロパティのデリゲートを作成することを決めたとこれまで得た:(結果は約30〜40倍の高速化、従来の方法を使用するよりも、非常に良好であったリフレクションパフォーマンス - デリゲートを作成する(プロパティC#)

TestClass cwp = new TestClass(); 
var propertyInt = typeof(TestClass).GetProperties().Single(obj => obj.Name == "AnyValue"); 
var access = BuildGetAccessor(propertyInt.GetGetMethod()); 
var result = access(cwp); 
static Func<object, object> BuildGetAccessor(MethodInfo method) 
{ 
    var obj = Expression.Parameter(typeof(object), "o"); 

    Expression<Func<object, object>> expr = 
     Expression.Lambda<Func<object, object>>(
      Expression.Convert(
       Expression.Call(
        Expression.Convert(obj, method.DeclaringType), 
        method), 
       typeof(object)), 
      obj); 

    return expr.Compile(); 
} 

PropertyInfo.GetValue (obj, null);

問題は次のとおりです。同じように動作するプロパティのSetValueを作成するにはどうすればよいですか?残念ながら、方法はありませんでした。

アプリケーションの構造上、<T>のメソッドを使用できないため、私はそうしています。

+0

"私のアプリケーションの構造上、" < T > "というメソッドを使用することができないので、私はそうしています - あなたのNETFXバージョン<2.0?アプリケーションでジェネリックを使用できないのはなぜですか? –

+0

また、あなたのプロパティのデリゲートを作成することはリフレクションと関係があり、リフレクションを使ってどのような問題を解決しようとしていますか? –

+0

代理人は、パフォーマンスが大幅に向上し、動的に使用することができます。動的呼び出しを使用する必要がある場合は、これらのオプションが優先されます。 – GregRos

答えて

15

これはあなたのために働く必要があります。

static Action<object, object> BuildSetAccessor(MethodInfo method) 
{ 
    var obj = Expression.Parameter(typeof(object), "o"); 
    var value = Expression.Parameter(typeof(object)); 

    Expression<Action<object, object>> expr = 
     Expression.Lambda<Action<object, object>>(
      Expression.Call(
       Expression.Convert(obj, method.DeclaringType), 
       method, 
       Expression.Convert(value, method.GetParameters()[0].ParameterType)), 
      obj, 
      value); 

    return expr.Compile(); 
} 

使用法:

var accessor = BuildSetAccessor(typeof(TestClass).GetProperty("MyProperty").GetSetMethod()); 
var instance = new TestClass(); 
accessor(instance, "foo"); 
Console.WriteLine(instance.MyProperty); 

TestClass付:

public class TestClass 
{ 
    public string MyProperty { get; set; } 
} 

プリントアウト:

foo

2

ダイナミックタイプを使用します。彼らはフードの下で反射を使用しますが、それはより速くです。

そうでなければ...寛容なライセンスを持つそこに無料の高速化反射ライブラリのトンが

があります。私はあなたをリンクしますが、あまりにも多くあります、そして、あなたに合っているかどうかわかりません。ちょうどあなたが好きなものを見つけたら、それを試してみてください。

しかし、そうかもしれませんが、実際には反射がなら答えはです。多くの場合、他にも解決策があります。

編集:要求されたよう...

http://geekswithblogs.net/SunnyCoder/archive/2009/06/26/c-4.0-dynamics-vs.-reflection.aspx
http://theburningmonk.com/2010/09/performance-test-dynamic-method-invocation-in-csharp-4/
http://www.mssoftwareconsulting.com/msswc/blog/post/C-40-and-dynamic-performance.aspx

それは共通の知識は私の知る限りです。

+0

申し訳ありません?なぜ否定的な投票ですか? – GregRos

+1

**他の方法がない限り、ダイナミクスは反射、IMOに使用しないでください**。あなたはより速い*をサポートするいくつかのデータを投稿できますか? ...そして、OPがリクエストする方法でダイナミクスを使用する例は?これらは否定的な投票の理由のいくつかであるかもしれません... – IAbstract

+0

彼は動的な呼び出しを使用しています。例えば。メソッド、プロパティなどを設定します。これは**正確に**あなたがダイナミクスで行うことです。 – GregRos

10

パフォーマンスが鍵であれば、CreateDelegateの方が良いと思います。事前にメソッドのシグネチャを知っているので、PropertyInfoGetGetMethodGetSetMethodだけです。デリゲートを作成して、同じシグネチャで直接メソッドを実行することができます。式は代理人にいくつかのロジック(メソッドハンドルを持たないロジック)を構築する必要がある場合に適しています。私はこの問題に異なる経路上のいくつかのベンチマークをした約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を書いていました。

関連する問題