Ninject:如何动态地将通用类型注入绑定模板对象

时间:2015-07-23 02:01:30

标签: c# generics ninject

我有一个我在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;
    }
}

1 个答案:

答案 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));
    }
}

如果你不需要

,不要使用魔法

但我认为更重要的问题是:你为什么要这样做? 您如何知道要执行某些操作的实体类型和实体列表? 在大多数情况下,有一种替代方式,不涉及那么多“魔术”。