简体   繁体   English

Ninject:如何将泛型类型动态注入绑定的模板对象

[英]Ninject: How To Dynamically Inject Generic Type into Bound Template Object

I have a generic template class that I have configured in my Ninject configuration. 我有一个在Ninject配置中配置的通用模板类。

Template Class: 模板类别:

public Repository<T> : IRepository<T>
{
    //...
}

Ninject Configuration: Ninject配置:

container.Bind(typeof(IRepository<>)).To(typeof(Repository<>));

Also, I have a class that needs to dynamically create multiple instances of IRepository<T> , in which T is dynamic for each instance. 另外,我有一个类需要动态创建IRepository<T>多个实例,其中T对于每个实例都是动态的。

Is there a way to do this with Ninject? Ninject有办法做到这一点吗? The pseudo-code would be something as follows: 伪代码将如下所示:

foreach(Type genericType in repositoryTypes)
{
    var tempRepository = WebManager.Get(IRepository<genericType>); //how should this actually be?

    //do stuff with tempRepository
}

The WebManager would have something like below: WebManager的内容如下:

public static class WebManager 
{
    public static object Get(Type t)
    {
        object service = GlobalConfiguration.Configuration.DependencyResolver.GetService(t);
        return service;
    }
}

Of course this works, it's very simple: 当然可以,这很简单:

foreach(Type genericType in repositoryTypes)
{
    object tempRepository = WebManager.Get(typeof(IRepository).MakeGenericType(genericType));
    //do stuff with tempRepository
}

But then it get's trickier. 但是,这变得更加棘手。 How will you use this object ? 您将如何使用该object You'll need to use reflection. 您将需要使用反射。 It's simpler to use it once than for every call. 使用一次比每次调用都简单。 So we can adjust/write the code as follows: 因此,我们可以按以下方式调整/编写代码:

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();
    }
}

and just for reference, this is a test showing that it works: 仅供参考,这是一个测试表明它有效:

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

Don't employ magic if you don't have to 如果不需要,请不要使用魔术

But i think the more important question is: why do you want to do this? 但是我认为更重要的问题是:您为什么要这样做? How do you know the list of entity types and entities to do something for? 您如何知道要执行某操作的实体类型和实体的列表? In most cases there's an alternative way which doesn't involve that much "magic". 在大多数情况下,有另一种方法不涉及太多的“魔术”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM