2012-01-09 6 views
1

私はこの1と同様の方法を持っていることを反映しています。誰も言及するReflectionはパフォーマンスが悪いと言っているので、結果をキャッシュして、各varに対して1回のみ反映させるようにしたい。例:キャッシュは、プロパティ名

GetVariableName(() => Model.Field1) // Does Reflection. 
GetVariableName(() => Model.Field2) // Does Reflection. 
GetVariableName(() => Model.Field1) // Uses Cache. 
GetVariableName(() => Model.Field2) // Uses Cache. 

私は、パラメータを記録するために、この使用率を使用していると私はAsp.net Mvc3アプリケーションでJQueryセレクタ

$('#'+ @(GetVariableName(()=> Model.FieldName))).Val(); 

任意のアイデアを生成するためにそれを使用して起動したいですか?

+2

これは反射ではありません。コンパイラはすでにあなたのために式ツリーを構築しています。 – Eranga

+0

@ Eranga、あなたは親切で、あなたが詳細に書いたことを説明できますか? – gdoron

+0

これは反映ではありません。せいぜい危険なように見える表現変数をキャッシュしたいと思っています。 –

答えて

2
リフレクションを言及

誰もがそれはパフォーマンス

確かに悪いのですが、この場合にはすでにラムダ式からのMemberInfoを持っていると言います。コンパイラはすでに式ツリーを構築しています。あなたは遅いものである反射を使ってそれをフェッチする必要はありません。高価なものは次のとおりです。

static string GetVariableName(string expression) 
{ 
    // use reflection to find the property given the string and once you have the property 
    // get its name 
    ... 
} 

これは、ASP.NET MVCの強く型付けされたヘルパーの仕組みです。強く型付けされたラムダ式のバージョンを使用する場合は、何もキャッシュする必要はありません。

+0

hmmm ...ありがとう。 「本当の」反射の例を挙げてください。まさに「反射ホラー」とは何ですか? – gdoron

+0

ところで、jqueryセレクタを構築する方法についてどう思いますか?このようにして、あるプロパティ名をリファクタリングする場合、Jqueryコードをすべて変更する必要はありません。 – gdoron

+0

@ gdoron、[GetProperty](http://msdn.microsoft.com/en-us/library/kz0a8sxy.aspx)メソッドは、文字列を指定してプロパティを取得するためにリフレクションを使用する良い例です。 PropertyInfoとオブジェクトのインスタンスを取得したら、その値をフェッチすることもできます。あなたの2番目の質問に関しては、私はJavaScriptとサーバーのサイドコードを混ぜることは絶対に恐ろしいと思います。個人的に私はJavaScriptを別々のファイルに保存しています。 –

0

属性を使用したと思われましたか?モデルに一度反映させ、その結果をキャッシュすることができます。非キャッシュされた対キャッシュされた名前をベンチマーク

[AttributeUsage(AttributeTargets.Property, AllowMultiple= false)] 
class JQueryFieldNameAttribute : Attribute { 

    public string Name { get; private set; } 

    public JQueryFieldNameAttribute(string name) 
    { 
     Name = name; 
    } 
} 

class Model { 
    [JQueryFieldName("#clientid")] 
    public string Foo { get; set; } 
} 

void Main() 
{ 
    var type = typeof(Model); 

    var attributes = type.GetProperties() 
         .SelectMany (t => t.GetCustomAttributes(typeof(JQueryFieldNameAttribute), true)); 

    var cache = new Dictionary<int, IEnumerable<JQueryFieldNameAttribute>>(); 

    // Cache results for this type only 
    cache.Add(type.GetHashCode(), attributes); 

    foreach (JQueryFieldNameAttribute a in attributes) 
    { 
     Console.WriteLine (a.Name); 
    } 
} 
1
あなたはこのような何かを行うことができるはず

...

class Foo { 

    public Foo() { 
     m_Field1Name = new Lazy<string>(() => GetVariableName(() => Field1)); 
     m_Field2Name = new Lazy<string>(() => GetVariableName(() => Field2)); 
    } 

    public int Field1 { get; set; } 
    public int Field2 { get; set; } 

    public string Field1Name { 
     get { 
      return m_Field1Name.Value; 
     } 
    } 
    readonly Lazy<string> m_Field1Name; 

    public string Field2Name { 
     get { 
      return m_Field2Name.Value; 
     } 
    } 
    readonly Lazy<string> m_Field2Name; 

    public static string GetVariableName<T>(Expression<Func<T>> expression) { 
     var body = expression.Body as MemberExpression; 
     return body.Member.Name; 
    } 

} 

...

class Program { 

    static void Main(string[] args) { 

     var foo = new Foo(); 

     const int count = 1000000; 
     var sw = new Stopwatch(); 

     sw.Restart(); 
     for (int i = 0; i < count; ++i) { 
      string name1 = foo.Field1Name; 
      string name2 = foo.Field2Name; 
     } 
     sw.Stop(); 
     Console.Write("Cached:\t\t"); 
     Console.WriteLine(sw.Elapsed); 

     sw.Restart(); 
     for (int i = 0; i < count; ++i) { 
      string name1 = Foo.GetVariableName(() => foo.Field1); 
      string name2 = Foo.GetVariableName(() => foo.Field2); 
     } 
     sw.Stop(); 
     Console.Write("Non-cached:\t"); 
     Console.WriteLine(sw.Elapsed); 

    } 

} 

このプリントを有意差を示しています。

Cached:  00:00:00.0176370 
Non-cached: 00:00:12.9247333 
+0

あなたのご意見ありがとうございます。しかし今、クラスは取得するすべてのプロパティを「知っている」必要があります。 – gdoron

+0

@gdoronあなたの例では、 '()=> Model.Field1'と書くと、コンパイル時にプロパティをすでに知っていることになります。プロパティと同じクラスの名前をキャッシュするかどうかは、別の問題です。既存のクラスを変更できない場合は、キャッシュ目的のためだけに新しいクラスを作成できます。 'GetVariableName(()=> default(Foo).Field1)'と書くことができます。実際にはラムダは決して呼び出されないので、 'default (Foo) 'がnullです。 –

関連する問題