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

发布于 2024-12-21 03:14:29 字数 986 浏览 2 评论 0原文

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

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

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

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

I'm trying to scan for a set of components that implement a specific base class in the assemblies in the same directory as my application. I need to do this as a sort of plugin-style architecture, as my application uses these types to populate other components.

Ninject.Extensions.Conventions supports scanning assemblies in the local directory, so I decided to give it a shot.

The problem is that the binding generators that library provides (DefaultBindingGenerator and RegexBindingGenerator) will only bind components to interfaces that they implement. They won't bind to non-interface base types.

How do I use this library to bind by convention to a base class, rather than an interface?

I am using the version currently on NuGet - 2.2.0.5

My current convention-based binding code looks like this:

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

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

    x.InTransientScope();
});

When I try to resolve the components, nothing is returned:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

彼岸花似海 2024-12-28 03:14:29

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

我这样使用它:

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!

In the current code base up on GitHub, you can use the BaseBindingGenerator.

In the codebase I have (the one currently on NuGet - 2.2.0.5), I solved this using a custom IBindingGenerator. It was fairly simple to write once I looked at 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);
    }
}

I used it like this:

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!
野心澎湃 2024-12-28 03:14:29

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

Just an update on Merlyn´s answer, I am using ninject extensions conventions 3.2, and the signature has changed a little bit...

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) };
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文