我有一个网站使用以下代码返回存储库,它将接受一个接口并返回它找到的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);
}
答案 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)。