方法工厂 - 案例与反射 [英] Method Factory - case vs. reflection

查看:14
本文介绍了方法工厂 - 案例与反射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

前几天我遇到了一些代码,我想知道这是否是最好的方法.我们有一个方法,它从一些 Web 表单数据中获取一个字符串,a 根据传入的字符串对对象执行某些操作.目前,它使用反射来确定要采取的操作,但我想知道 switch 语句是否会更好.

I came across some code the other day and I wondered if that was the best way to do it. We have a method that takes a string from some web form data a does something to an object based on the string that is passed in. Currently, it uses reflection to figure which action to take, but I wondered if a switch statement would be better.

例子:

正如卢塞诺所说,我为代表添加了第三个选项

I added a third option for delegates as noted by Lucerno

public class ObjectManipulator
{
    private void DoX(object o) { }
    private void DoY(object o) { }
    private void DoZ(object o) { }

    public void DoAction(string action, object o)
    {
        switch (action)
        {
            case "DoX":
                DoX(o);
                break;
            case "DoY":
                DoY(o);
                break;
            case "DoZ":
                DoZ(o);
                break;
            default:
                throw new Exception(string.Format(
                    "Cannot locate action:{0}", action));
        }
    }

    public void DoActionViaReflection(string action, object o)
    {
        MethodInfo method = typeof(ObjectManipulator).
            GetMethod(action, new Type[] { typeof(object) });
        if (method == null)
        {
            throw new Exception(string.Format(
                "Cannot locate action:{0}", action));
        }
        else
        {
            method.Invoke(this, new object[] { o });
        }
    }
    private Dictionary<string, Action<object>> _methods;
    public ObjectManipulator()
    {
        _methods = new Dictionary<string, Action<object>>()
        {
            {"DoX", o => DoX(o)},
            {"DoY", o => DoY(o)},
            {"DoZ", o => DoZ(o)}
        };
    }
    public void DoActionViaDelegates(string action, object o)
    {
        if (!_methods.ContainsKey(action))
        {
            throw new Exception(string.Format(
                "Cannot locate action:{0}", action));
        }
        else
        {
            _methods[action](o);
        }
    }

}

第一个示例使用了开关,如您所见,可能会变得非常冗长.第二个要短得多,但使用反射,我知道有些人会像瘟疫一样避免.

The first example uses the switch and as you can see could get very verbose. The second is much shorter, but uses reflection, which I know some people avoid like the plague.

一种方法的性能会明显优于另一种吗?

Will one method perform significantly better that the other?

如果有 100 个不同的操作而不是只有 3 个,性能会改变吗?

Would the performance change if there were 100 different actions instead of just 3?

如果您正在阅读代码,您更愿意在代码中看到哪个?

Which do you rather see in your code if you were reading it?

推荐答案

第一种情况几乎总是更快.然而,它的性能来自于它可以在编译时提前绑定,但这也是它最大的缺点:例如,这种方法不能处理动态加载的程序集,而且更容易出错,因为它是命令式而不是声明式.(例如,忘记一个新实施的动作是一件很快就会发生的事情.)

The first case will almost always be faster. However, its performance comes from the fact that it can be early bound during compile time, but that is its biggest drawback as well: this approach cannot, for instance, handle dynamically loaded assemblies, and it is much more error-prone since it is imperative and not declarative. (Forgetting a newly implemented action for instance is a thing which could happen quickly.)

我通常的方法是在发现时使用反射来实现这样的模式,但在调用时使用委托.这为您提供了反射方法的灵活性,其性能非常接近早期绑定方法.

My usual approach is to use reflection to implement such patterns during discovery time, but to use delegates at invocation time. This gets you the flexibility of the reflection approach with performance very close to the early-bound approach.

  • 发现阶段:使用反射来查找成员(使用属性、接口、签名和/或编码约定).在您的情况下,您始终具有相同的签名,因此要使用的委托将是 Action<object>.将这些成员添加到 Dictionary> 实例,使用 CreateDelegate().

  • Discovery phase: use reflection to find the members (using attributes, interfaces, signatures, and/or coding conventions). In your case you always have the same signature, so the delegate to use would be Action<object>. Add those members to a Dictionary<string, Action<object>> instance, creating a delegate from the MethodInfo using CreateDelegate().

调用阶段:通过key获取delegate并调用,非常简单(这里假设字典名为methods):methods[action](o)

Invocation phase: get the delegate via its key and invoke it, which is very simple (here assuming the dictionary is called methods): methods[action](o)

这篇关于方法工厂 - 案例与反射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆