我有一个我在Ninject配置中配置的通用模板类。
模板类:
public Repository<T> : IRepository<T>
{
//...
}
Ninject配置:
container.Bind(typeof(IRepository<>)).To(typeof(Repository<>));
另外,我有一个类需要动态创建IRepository<T>
的多个实例,其中T对于每个实例都是动态的。
有没有办法用Ninject做到这一点?伪代码如下:
foreach(Type genericType in repositoryTypes)
{
var tempRepository = WebManager.Get(IRepository<genericType>); //how should this actually be?
//do stuff with tempRepository
}
WebManager将具有如下内容:
public static class WebManager
{
public static object Get(Type t)
{
object service = GlobalConfiguration.Configuration.DependencyResolver.GetService(t);
return service;
}
}
答案 0 :(得分:2)
当然这很有效,但很简单:
foreach(Type genericType in repositoryTypes)
{
object tempRepository = WebManager.Get(typeof(IRepository).MakeGenericType(genericType));
//do stuff with tempRepository
}
然而它变得更加棘手。你将如何使用这个object
?你需要使用反射。使用它比使用每次通话更简单。所以我们可以按如下方式调整/编写代码:
internal class Foo
{
private static readonly MethodInfo DoStuffToRepositoryForMethod =
typeof(Foo).GetMethod(
"DoStuffToRepositoryFor",
BindingFlags.Instance | BindingFlags.NonPublic);
private readonly IResolutionRoot resolutionRoot;
public Foo(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public void DoStuffToRepositories(params Type[] entityTypes)
{
foreach (Type entityType in entityTypes)
{
MethodInfo doStuffMethod = DoStuffToRepositoryForMethod
.MakeGenericMethod(entityType);
doStuffMethod.Invoke(this, new object[0]);
}
}
private void DoStuffToRepositoryFor<T>()
{
var repository = this.resolutionRoot.Get<IRepository<T>>();
repository.DoSomething();
}
}
仅供参考,这是一项测试,表明它有效:
public class Test
{
[Fact]
public void TestIt()
{
var kernel = new StandardKernel();
kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>));
var foo = kernel.Get<Foo>();
foo.DoStuffToRepositories(typeof(string), typeof(int));
}
}
但我认为更重要的问题是:你为什么要这样做? 您如何知道要执行某些操作的实体类型和实体列表? 在大多数情况下,有一种替代方式,不涉及那么多“魔术”。