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

时间:2011-12-14 05:40:56

标签: .net dependency-injection ninject

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

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

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

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

我正在使用the version currently on 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();
});

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

var myTypes = Kernel.GetAll<BaseType>();
int count = myTypes.Count(); // Always returns zero

2 个答案:

答案 0 :(得分:6)

the current code base up on GitHub中,您可以使用the BaseBindingGenerator

在我拥有的代码库(当前在NuGet上的那个 - 2.2.0.5)中,我使用自定义IBindingGenerator解决了这个问题。一看到the sources for the existing binding generators就写起来相当简单。

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

我这样用过:

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!

答案 1 :(得分:0)

只是关于Merlyn答案的更新,我正在使用ninject扩展约定3.2,签名已经改变了一点......

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

    public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
    {
        if (type.IsInterface || type.IsAbstract || type.BaseType != baseType)
        {
            return Enumerable.Empty<IBindingWhenInNamedWithOrOnSyntax<object>>();
        }

        return new [] { bindingRoot.Bind(baseType).To(type) };
    }
}