Chr*_*sic 5 c# reflection dynamic-class-creation
目前,我在实现接口的类中实现了我的VaryByCustom功能 IOutputCacheVaryByCustom
public interface IOutputCacheVaryByCustom
{
    string CacheKey { get; }
    HttpContext Context { get; }
}
实现此接口的类有一些约定,类的名称将为"OutputCacheVaryBy_______",其中空白是从页面上的varyByCustom属性传入的值.另一个约定是Context将通过构造函数注入来设置.
目前我的基础是enum和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 + varyByCustomTypeArg唯一的构造函数参数将是context我意识到我可以绕过需要这个荣耀的if else块并且可以实例化我自己的对象Activator.
有了这个说法,反射不是我的强项,我知道这Activator与静态创作和其他生成对象的方法相比要慢得多.有什么理由我应该坚持使用当前的代码,还是应该使用Activator或以类似的方式创建我的对象?
我见过博客http://www.smelser.net/blog/post/2010/03/05/When-Activator-is-just-to-slow.aspx,但我不确定这是怎么回事因为我在运行时使用类型而不是静态T.
如果反射对你来说太慢了.你可以让你自己的ObjectFactory工作.这真的很容易.只需在界面中添加新方法即可.
    public interface IOutputCacheVaryByCustom
    {
        string CacheKey { get; }
        IOutputCacheVaryByCustom NewObject();
    }
比创建一个包含对象模板的静态只读CloneDictionary.
    static readonly
        Dictionary<VaryByCustomType, IOutputCacheVaryByCustom> cloneDictionary
        = new Dictionary<VaryByCustomType, IOutputCacheVaryByCustom>
        {
            {VaryByCustomType.IsAuthenticated, new OutputCacheVaryByIsAuthenticated{}},
            {VaryByCustomType.Roles, new OutputCacheVaryByRoles{}},
        };
完成后,您可以使用已有的枚举来选择字典中的模板并调用NewObject()
        IOutputCacheVaryByCustom result = 
             cloneDictionary[VaryByCustomType.IsAuthenticated].NewObject();
就是这么简单.您必须实现的NewObject()方法将通过直接创建对象来返回新的实例.
    public class OutputCacheVaryByIsAuthenticated: IOutputCacheVaryByCustom
    {
        public IOutputCacheVaryByCustom NewObject() 
        {
            return new OutputCacheVaryByIsAuthenticated(); 
        }
    }
这就是你需要的全部.它的速度令人难以置信.
您实际上并不需要使用反射,因为它是一组相当有限的可能值。但是你可以做这样的事情
internal class Factory<T,Arg>
{
   Dictionary<string,Func<Arg.T>> _creators;
   public Factory(IDictionary<string,Func<Arg,T>> creators)
  {
     _creators = creators;
  }
}
并将你的创作逻辑替换为
_factory[varyByCustomTypeArg](context);
它不像开关那么快,但它保持结构和使用很好地分开
| 归档时间: | 
 | 
| 查看次数: | 1382 次 | 
| 最近记录: |