2011-08-12 6 views
3

多くの異なるListプロパティを持つデータオブジェクトがあります。それぞれのリストに対して異なるコマンドを作成するのではなく、単一のAddObjectコマンドを使用したいので、次のコードが思い浮かびました。Reflectionを使用してViewModelで汎用タイプのコマンドを作成する際の弱点は何ですか?

これを使用すると何か面白いことはありますか?私はパフォーマンスが遅くなるかもしれないと思ったが、正直なところ違いは見られなかった。

public MyViewModel() 
{ 
    _addCommand = new RelayCommand<IEnumerable>(AddGenericObject); 

    // Old code.... defines an Add command per list 
    // _addAddressCommand = new RelayCommand(() => AddObject<Address>(AddressList)); 
    // _addPhoneCommand = new RelayCommand(() => AddObject<Phone>(PhoneList)); 
    // ... etc 
} 

private void AddGenericObject(IEnumerable list) 
{ 
    // Find Add Method 
    var addMethod = this.GetType() 
     .GetMethod("AddObject", BindingFlags.NonPublic | BindingFlags.Instance); 

    // Created Generic Add Method 
    Type genericType = list.GetType().GetGenericArguments()[0]; 
    var genericAddMethod = addMethod.MakeGenericMethod(genericType); 

    // Invoke Method 
    genericAddMethod.Invoke(this, new object[] { list }); 
} 

private void AddObject<T>(EntityCollection<T> list) 
    where T : EntityObject, new() 
{ 
    var newItem = new T(); 
    list.Add(newItem); 
} 

それは、このようなもので、XAMLで使用されます。一言で

<Button Content="New Address" 
     Command="{Binding AddCommand}" 
     CommandParameter="{Binding AddressList}" /> 

<Button Content="New Phone" 
     Command="{Binding AddCommand}" 
     CommandParameter="{Binding PhoneList}" /> 
+0

以下のコメントが示唆するように、パフォーマンスが反射して大きな問題です。キャッシュ機能を使用して、リフレクションの結果をキャッシュに入れて、パフォーマンスをスピードアップしてください。 – Jethro

+0

この文脈で大丈夫ですが、壊れやすいものです。リストが汎用ではない場合、または異なるタイプのインスタンスが含まれている場合はどうなりますか?明らかに、あなた自身のコードベース内で、あなたはそれを簡単に制御することができます。 ICommandはイベントのようなソースを提供していません。そうでなければ、添付されたプロパティを使ってターゲットタイプを指定することができます。私は添付のプロパティが大好きです。彼らは子犬のキスのように私を幸せにする。 – Will

答えて

1

- パフォーマンス、しかし、あなたは、コードのベンチマークそれを取り除く前に - それはあなたのニーズに十分に速いかもしれません。

1

リフレクションの使用を考慮する場合、パフォーマンスは常に最大の要因です。可能であれば、リフレクションの使用を避けてください。

0

JamesとDrorが提案しているように、Preformanceは大きな要因です。メソッドをキャッシュするには、次の操作を行います。

private MethodInfo cachedMethod = null; 
    private void AddGenericObject(IEnumerable list) 
    { 
     if (cachedMethod == null) 
     { 
      // Find Add Method 
      var addMethod = this.GetType() 
       .GetMethod("AddObject", BindingFlags.NonPublic | BindingFlags.Instance); 

      // Created Generic Add Method 
      var genericType = list.GetType().GetGenericArguments()[0]; 
      cachedMethod = addMethod.MakeGenericMethod(genericType); 
     } 

     // Invoke Method 
     cachedMethod.Invoke(this, new object[] { list }); 
    } 
+0

メソッドは多くの異なるジェネリック型で呼び出される必要があり、ジェネリック型メソッドの定義を1つだけキャッシュするので、これはうまくいくとは思いません。 – Rachel

+1

すべての型がIEnumerableを継承するため、私はそれができないと思います。私が間違っている場合は、List またはDictionary を作成して、その特定のタイプをキャッシュしているかどうかを確認するだけです。私はあなたがそれを見たい場合は、このいくつかの例を持っています。 – Jethro

0

、CommandオブジェクトとしてのFreezableを使用することにしたDependencyPropertyとして(オブジェクトの)タイプのアクションの委任を与え、そしてConverterParameterや変換などのメソッド名を受け入れコンバータを使用することですこれを行うための私の方法コレクションへのバインド中に、コレクションのAddメソッド(またはconverterparameterとして使用するメソッド名)の代理人へのコレクションへの参照。この方法では、バインディングされたコレクションオブジェクト自体が交換されたときにのみリフレクションのコストが発生します。これは、同じコレクションを維持してアイテムを追加したり削除したりするためです。

あなたがサンプルコードを探しているなら、あなたはこのブログの記事をチェックアウトする場合がありますhttp://wpfglue.wordpress.com/2012/05/07/commanding-binding-controls-to-methods/

関連する問題