动态创建类而不是使用 switch 块的最佳方法
目前,我在实现接口 IOutputCacheVaryByCustom
的类中实现了 VaryByCustom 功能。
public interface IOutputCacheVaryByCustom
{
string CacheKey { get; }
HttpContext Context { get; }
}
实现此接口的类有一些约定,该类的名称将为“OutputCacheVaryBy_______”,其中空白是传入的值来自页面上的 VariableByCustom 属性。另一个约定是 Context 将通过构造函数注入来设置。
目前,我基于一个枚举和一个类似于 switch 语句
public override string GetVaryByCustomString(HttpContext context,
string varyByCustomTypeArg)
{
//for a POST request (postback) force to return back a non cached output
if (context.Request.RequestType.Equals("POST"))
{
return "post" + DateTime.Now.Ticks;
}
var varyByCustomType = EnumerationParser.Parse<VaryByCustomType?>
(varyByCustomTypeArg).GetValueOrDefault();
IOutputCacheVaryByCustom varyByCustom;
switch (varyByCustomType)
{
case VaryByCustomType.IsAuthenticated:
varyByCustom = new OutputCacheVaryByIsAuthenticated(context);
break;
case VaryByCustomType.Roles:
varyByCustom = new OutputCacheVaryByRoles(context);
break;
default:
throw new ArgumentOutOfRangeException("varyByCustomTypeArg");
}
return context.Request.Url.Scheme + varyByCustom.CacheKey;
}
,因为我总是知道该类将是 OutputCacheVaryBy + VarByCustomTypeArg
并且唯一的构造函数参数将是 context
I意识到我可以绕过这个美化的 if else 块,并且可以使用 Activator 实例化我自己的对象。
话虽如此,反射并不是我的强项,而且我知道 Activator 与静态创建和其他生成对象的方法相比要慢得多。我是否应该坚持使用当前代码,或者应该使用 Activator 或类似的方式来创建对象?
我看过博客 http://www.smelser.net/blog/post/2010/03/05/When-Activator-is-just-to-slow.aspx 但我不太确定这将如何应用,因为我在运行时使用类型而不是静态 T。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果反射对你来说太慢。您也许可以让自己的 ObjectFactory 正常工作。
这真的很容易。只需向您的界面添加一个新方法即可。
然后创建一个保存对象模板的静态只读 CloneDictionary。
如果您完成了此操作,您可以使用已有的枚举来选择字典中的模板并调用 NewObject()
就是这么简单。您必须实现的 NewObject() 方法将通过直接创建对象来返回一个新实例。
这就是您所需要的。而且速度快得令人难以置信。
If Reflection is too slow for you. You can probably get your own ObjectFactory working.
It's really easy. Just add a new method to your interface.
Than create a static readonly CloneDictionary that holds the object templates.
If you finished with that, you can use the enum that you already have in order to select the template in the dictionary and call NewObject()
Is just that simple. The NewObject() method you have to implement, will return a new Instance by directly creating the object.
That's all you need to have. And it's incredible fast.
您实际上并不需要使用反射,因为它是一组相当有限的可能值。然而,你可以做这样的事情
,并用它代替你的创建逻辑,
它不像开关那么快,但它保持构造和使用很好地分开
You don't really need to use reflection since it's a rather limited set of possible values. You could however do something like this
and substitute your creation logic with
it's not as fast as a switch but it keeps construction and use nicely seperate
我真的很喜欢让其他人来处理对象创建。例如,如果我需要接口的不同具体实现,IoC 容器就为我创造了奇迹。
作为使用 unity 的一个简单示例,您有一个配置部分将密钥链接到实现,如下所示:
并且您的创建看起来会简单得多,如下所示:
或者如果 IoC 不是一个选项,我会让工厂创建具体的类,所以您永远不会有担心你对它们的实际方法。
I really like to have object creation taken care of by someone else. For example if i need different concrete implementations of an interface an IoC container has worked wonders for me.
As a simple example using unity you have a configuration portion linking up keys to implementations like so:
and your creation would look much simpler like so:
Or if IoC is not an option i would let a factory create the concrete classes, so you never have to worry your actual methods about them.
继续使用 switch 语句。如果您只有几种可能的情况,那么您只是尝试使用巧妙的抽象来避免坐下来让程序的困难部分正常工作...
也就是说,从您的问题来看,它似乎使用
Activator
可能适合您。你测试过吗?真的是太慢了吗?或者,您可以在
Dictionary
中保留一堆工厂方法。如果您经常(在循环中)创建这些对象,我会使用它。然后,您还可以优化enum
的string
键并完成转换。变得更抽象只会隐藏这段代码的意图......Stay with the switch statement. If you only have a couple of possible cases like this, then you are just trying to use clever abstraction to avoid sitting down and getting the hard parts of your program working...
That said, from your question it seems using the
Activator
might work for you. Have you tested it? Was it really too slow?Alternatively, you could just keep a bunch of factory methods in a
Dictionary<string, Func<IOutputCacheVaryByCustom>
. This I would use, if you are creating these objects often (in a loop). You could then also optimize thestring
key to yourenum
and be done with the conversion. Going more abstract will just hide the intent of this piece of code...这是创建新对象的示例
一些信息:
还有一个示例,其中我将类包含到数组列表中:
Here is an example to create new object
Some infos:
Also an example where I get the class contained into an arraylist:
使用反射。
您可能必须在 typename 前添加命名空间:"My.Name.Space.OutputCacheVaryBy"。如果这不起作用,请尝试使用程序集限定名称:
Use reflection.
You might have to prefix typename with a namespace: "My.Name.Space.OutputCacheVaryBy". If that doesnt work, try with a assembly qualified name: