开发者

What are the downsides of using Reflection to create a Generic Type Command in my ViewModel?

I have a data object that has many different List properties. I want to use a single AddObject command instead of creating a different command for each List, so came up with the following code.

Is there any downsides you can see to using this? I thought performance might be slow, but I honestly haven't seen a difference.

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);
}

It is used in the XAML by something like th开发者_StackOverflowis:

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

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


In one word - performance, but before you rid of the code benchmark it - it might be fast enough for your needs.


Performance is always the biggest factor when considering the use of reflection. In general, you should try to avoid using reflection if you can.


Preformance is a big factor as James and Dror have suggested. You can do the following to cache the method.

    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 });
    }


My way of doing this would be to use a Freezable as Command object, give it a Delegate of type Action(of Object) as a DependencyProperty, and use a converter which accepts a method name as ConverterParameter and converts a reference to the collection into a Delegate to the collection's Add method (or whatever method's name you use as converterparameter) while binding to the collection. This way, the cost of reflection is only incurred when the bound collection object itself is exchanged, which should be fairly rare, since you want to keep the same collection and just add and remove items.

If you are looking for example code, you might want to check out this blog post: http://wpfglue.wordpress.com/2012/05/07/commanding-binding-controls-to-methods/

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜