问题描述
我碰到一些代码来了一天,我想知道这是否是做到这一点的最好办法。我们必须接受一个string一些Web表单的数据做一些事情,以基于传入的字符串的对象。目前,它使用反射来弄清楚要采取的行动,但我想,如果一个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.
例如:
编辑:我添加了代表第三个选项,由Lucerno指出
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.
-
Discovery阶段:使用反射找到部件(使用属性,接口,签名,和/或编码约定)。你的情况,你总是有相同的签名,所以委托使用的是
动作<对象>
。这些成员添加到词典<字符串,动作<对象>>
实例,创建从的MethodInfo
使用委托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 aDictionary<string, Action<object>>
instance, creating a delegate from theMethodInfo
usingCreateDelegate()
.
调用阶段:通过关键拿到委托并调用它,这是非常简单(这里假定该词典叫做方法
):方法[动作](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)
这篇关于方法厂 - 案例与反思的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!