如何使用Ninject Conventions库绑定到非接口的基本类型?

Mer*_*ham 4 .net dependency-injection ninject

我正在尝试扫描一组组件,这些组件在与我的应用程序相同的目录中的程序集中实现特定的基类.我需要将此作为一种插件式架构,因为我的应用程序使用这些类型来填充其他组件.

Ninject.Extensions.Conventions支持在本地目录中扫描程序集,所以我决定试一试.

问题是库提供的绑定生成器(DefaultBindingGeneratorRegexBindingGenerator)只会将组件绑定到它们实现的接口.它们不会绑定到非接口基类型.

如何使用此库按约定绑定到基类,而不是接口?

我正在使用当前在NuGet上的版本 - 2.2.0.5

我当前基于约定的绑定代码如下所示:

Kernel.Scan(x =>
{
    x.FromAssembliesMatching("*.dll");
    x.WhereTypeInheritsFrom<BaseType>();

    // I've tried both DefaultBindingGenerator and RegexBindingGenerator
    x.BindWith<DefaultBindingGenerator>();

    x.InTransientScope();
});
Run Code Online (Sandbox Code Playgroud)

当我尝试解析组件时,不会返回任何内容:

var myTypes = Kernel.GetAll<BaseType>();
int count = myTypes.Count(); // Always returns zero
Run Code Online (Sandbox Code Playgroud)

Mer*_*ham 6

GitHub上当前代码库了,就可以使用BaseBindingGenerator.

在我的代码库(当前在NuGet上的那个 - 2.2.0.5)中,我使用自定义解决了这个问题IBindingGenerator.一看到现有绑定生成器的源代码,编写起来相当简单.

public class BaseTypeBindingGenerator<TBase> : IBindingGenerator
{
    private static readonly Type baseType = typeof(TBase);

    public void Process( Type type, Func<IContext, object> scopeCallback,
        IKernel kernel )
    {
        if ( type.IsInterface || type.IsAbstract || type.BaseType != baseType)
        {
            return;
        }

        kernel.Bind(baseType).To(type).InScope(scopeCallback);
    }
}
Run Code Online (Sandbox Code Playgroud)

我用它是这样的:

Kernel.Scan(x =>
{
    x.FromAssembliesMatching("*.dll");
    x.WhereTypeInheritsFrom<BaseType>();

    x.BindWith<BaseTypeBindingGenerator<BaseType>>();

    x.InTransientScope();
});

// ...

var myTypes = Kernel.GetAll<BaseType>();
int count = myTypes.Count(); // Didn't return zero!
Run Code Online (Sandbox Code Playgroud)