【问题标题】:Find class that implements generic interface with Ninject使用 Ninject 查找实现通用接口的类
【发布时间】:2018-01-01 13:38:06
【问题描述】:

使用 Ninject,您可以像这样注册绑定:

Bind(typeof(IQueryHandler<,>)).To(typeof(QueryHandler<,>));

但就我而言,我不知道实际班级的名称。我只知道它实现了某个接口。

例如,假设我有以下内容:

public class CreatePageQueryHandler : IQueryHandler<CreatePage, string>
{
    public string Retrieve(CreatePage query)
    { ... }
}

只有一个类使用这些通用参数实现接口:IQueryHandler&lt;CreatePage, string&gt;

Ninject 有没有办法动态获取类的实例?比如:

kernel.Get<IQueryHandler<CreatePage, string>>(); // returns instance of: CreatePageQueryHandler 

请注意:

我不想在RegisterServices 方法中手动bind 这个。我正在寻找一种动态的方式来获取类的实例。

【问题讨论】:

    标签: c# ninject ninject.web.mvc


    【解决方案1】:

    使用此代码,您将获得所有实现 IQueryHandler 的类型。

    var types = AppDomain.CurrentDomain.GetAssemblies()
        .SelectMany(s => s.GetTypes())
        .Where(p => typeof(IQueryHandler).IsAssignableFrom(p));
    

    之后,您可以在 Ninject 中注册类型,也可以从其中一种类型手动创建实例:

    var instance = (IQueryHandler)Activator.CreateInstance(types.First());
    

    我没有测试这段代码,在 .Net Core 上有一种不同的方法可以从程序集中获取所有类型

    【讨论】:

    • 当没有非泛型 IQueryHandler 时,事情会变得有点复杂。在这个问题中似乎只有一个通用的IQueryHandler&lt;,&gt; 接口。
    【解决方案2】:

    Ninject 包含一个批量注册 API。例如,您可以使用以下绑定:

    kernel.Bind(
        x => x.FromAssembliesMatching("Fully.Qualified.AssemblyName*")
        .SelectAllClasses()
        .InheritedFrom(typeof(IQueryHandler<,>))
        .BindBase()
    );
    

    【讨论】:

    • 我已经安装了Ninject.Extensions.Conventions。但是bind 方法仍然不接受 lamda。我还有什么需要做的吗?
    • tbh,我不知道。我从this answer复制了这个例子。
    【解决方案3】:

    我认为您需要 Ninject 约定扩展。

    https://github.com/ninject/Ninject.Extensions.Conventions

    【讨论】: