实现存储库工厂C#

时间:2011-02-12 11:03:51

标签: c# asp.net generics

我有一个网站使用以下代码返回存储库,它将接受一个接口并返回它找到的firt实现,但是,我认为代码太慢并导致问题,有没有更好的方法来实现这个?

由于

 public T For<T>() where T : class
    {
        T returnVar = null;
        Assembly asm = Assembly.GetExecutingAssembly();

        var types = asm.GetTypes().Where(x => x.IsClass == true && x.Namespace != null && x.Namespace.StartsWith("Website.Core.Data.Repositories"));

        var result = types.Where(x => x.GetInterface(typeof(T).Name) != null);

        foreach (var x in result)
        {    
            var mi = x.GetConstructors();
            returnVar = (T)asm.CreateInstance(x.UnderlyingSystemType.ToString());
        }

        if (returnVar != null)
            return returnVar;
        else
            throw new Exception("No Repository for: " + typeof(T).Name);        
    }

4 个答案:

答案 0 :(得分:3)

一个明显的优化是缓存每个类型T的结果(如果你每次都想要新实例,那么缓存类型和构造函数信息)。

通过查看程序集来查找正确类型的结果不会在运行时更改。

另一方面,你可能最好使用IoC容器。

答案 1 :(得分:2)

为什么不尝试使用DI容器?像Autofac这样的东西应该很容易投入,即使没有知识,而且在运行时执行方面也很快(明显的替代方案是Windsor和结构图。听说Ninject性能的东西,但很久以前,不确定Microsoft Unity但可能不是速度最好的之一。)

阅读此页面上的代码。你会喜欢的吗:) http://code.google.com/p/autofac/wiki/Scanning

答案 2 :(得分:1)

这个怎么样:

private readonly Dictionary<Type, object> _items = new Dictionary<Type, object>();

    public T For<T>() where T : class
    {
        Type serviceType = typeof (T);
        lock (_items)
        {
            object instance;
            if (_items.TryGetValue(serviceType, out instance))
                return (T) instance;
        }


        Assembly asm = Assembly.GetExecutingAssembly();
        var types = asm.GetTypes().Where(x => x.IsClass
                                              && !x.IsAbstract
                                              && serviceType.IsAssignableFrom(x)
            );

        T returnVar = null;
        foreach (Type x in types)
        {
            ConstructorInfo[] mi = x.GetConstructors();
            returnVar = (T) asm.CreateInstance(x.UnderlyingSystemType.ToString());
        }

        if (returnVar != null)
        {
            lock (_items)
                _items.Add(serviceType, returnVar);
            return returnVar;
        }
        throw new Exception("No Repository for: " + typeof (T).Name);
    }

答案 3 :(得分:0)

我认为你的建筑物是一个临时的IOC容器。诀窍是在你第一次解决它之后保存接口和类之间的映射,这样你就不必每次都查找它。所以这个类需要状态才能提高性能。

但我可能会考虑阅读IOC并使用功能齐全的IOC容器(如Windsor Castle或Unity)来解析这些映射。我相信Windor Castle默认会将你前面有I的接口解析为没有它的类(IOrderProcessor - &gt; OrderProcessor)。