在 Ninject 中的所有程序集中加载模块

发布于 2024-12-11 18:11:22 字数 267 浏览 0 评论 0原文

我的项目中有几个类库,它们都使用 Ninject IoC 容器。我想在找到 INinjectModule 的地方一次性加载 StandardKernel 中的所有模块。所以我用了:

var kernel = new StandardKernel();
kernel.Load(AppDomain.CurrentDomain.GetAssemblies())

但这由于某种原因不起作用。有人可以帮忙吗?

I have couple of class libraries in my project and all are using Ninject IoC container. I wanted to load all the modules in a StandardKernel at one go wherever an INinjectModule is found. So I used:

var kernel = new StandardKernel();
kernel.Load(AppDomain.CurrentDomain.GetAssemblies())

But this doesn't work for some reason. Can anyone help?

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

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

发布评论

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

评论(4

输什么也不输骨气 2024-12-18 18:11:22

好吧,当声明了绑定但加载了其他模块而该模块尝试解析尚未加载的绑定时,通常会发生这种情况。发生这种情况是因为 List 的顺序可能不正确。

如果你认为是这样的话。遵循此决议。

我们的想法是,我们将为每个程序集提供一个引导程序,其中引导程序将负责按其逻辑顺序加载模块。

让我们考虑引导程序的接口(我们将使用它在程序集中查找引导程序)

public interface INinjectModuleBootstrapper
{
    IList<INinjectModule> GetModules();
}

现在考虑您的 DataAccess 程序集,实现 INinjectModuleBootstrapper:

public class DataAccessBootstrapper : INinjectModuleBootstrapper
{
    public IList<INinjectModule> GetModules()
    {
        //this is where you will be considering priority of your modules.
        return new List<INinjectModule>()
                   {
                       new DataObjectModule(),
                       new RepositoryModule(),
                       new DbConnectionModule()
                   };
        //RepositoryModule cannot be loaded until DataObjectModule is loaded
        //as it is depended on DataObjectModule and DbConnectionModule has
        //dependency on RepositoryModule
    }
}

这就是定义引导程序的方式code> 对于您的所有程序集。现在,从程序启动开始,我们需要加载所有模块的 StandardKernel 。我们将编写如下内容:

var assemblies = AppDomain.CurrentDomain.GetAssemblies();
return BootstrapHelper.LoadNinjectKernel(assemblies);

我们的 BootstrapperHelper 类是:

public static class BootstrapHelper
{
    public static StandardKernel LoadNinjectKernel(IEnumerable<Assembly> assemblies)
    {
        var standardKernel = new StandardKernel();
        foreach (var assembly in assemblies)
        {
            assembly
                .GetTypes()
                .Where(t =>
                       t.GetInterfaces()
                           .Any(i =>
                                i.Name == typeof(INinjectModuleBootstrapper).Name))
                .ToList()
                .ForEach(t =>
                             {
                                 var ninjectModuleBootstrapper =
                                     (INinjectModuleBootstrapper)Activator.CreateInstance(t);

                                 standardKernel.Load(ninjectModuleBootstrapper.GetModules());
                             });
        }
        return standardKernel;
    }
}

Well, this often happens when bindings are declared but other modules are loaded where that module tries to resolve a binding which has not loaded yet. This happens because List<INinjectModule> may not in the right order.

If you think this is the case. Follow this resolution.

The idea is we will have a bootstapper for each assembly, where the bootstrapper will be responsible to load the modules in its logical order.

Let us consider an interface for bootstrapper (this we will use to find the bootstrapper in an assembly)

public interface INinjectModuleBootstrapper
{
    IList<INinjectModule> GetModules();
}

Now consider for your DataAccess assembly, implement the INinjectModuleBootstrapper:

public class DataAccessBootstrapper : INinjectModuleBootstrapper
{
    public IList<INinjectModule> GetModules()
    {
        //this is where you will be considering priority of your modules.
        return new List<INinjectModule>()
                   {
                       new DataObjectModule(),
                       new RepositoryModule(),
                       new DbConnectionModule()
                   };
        //RepositoryModule cannot be loaded until DataObjectModule is loaded
        //as it is depended on DataObjectModule and DbConnectionModule has
        //dependency on RepositoryModule
    }
}

This is how you defne the Bootstrapper for all your assembly. Now, from your program startup, we need the StandardKernel where all the modules are loaded. We will write something like this:

var assemblies = AppDomain.CurrentDomain.GetAssemblies();
return BootstrapHelper.LoadNinjectKernel(assemblies);

And our BootstrapperHelper class is:

public static class BootstrapHelper
{
    public static StandardKernel LoadNinjectKernel(IEnumerable<Assembly> assemblies)
    {
        var standardKernel = new StandardKernel();
        foreach (var assembly in assemblies)
        {
            assembly
                .GetTypes()
                .Where(t =>
                       t.GetInterfaces()
                           .Any(i =>
                                i.Name == typeof(INinjectModuleBootstrapper).Name))
                .ToList()
                .ForEach(t =>
                             {
                                 var ninjectModuleBootstrapper =
                                     (INinjectModuleBootstrapper)Activator.CreateInstance(t);

                                 standardKernel.Load(ninjectModuleBootstrapper.GetModules());
                             });
        }
        return standardKernel;
    }
}
压抑⊿情绪 2024-12-18 18:11:22

您应该检查的另一件事是扩展 NinjectModule 的类是否是公共的,否则它将在程序集中不可见。

Another thing you should check is if the class that extends NinjectModule is public, otherwise it wont be visible in the Assembly.

相思故 2024-12-18 18:11:22

我认为使用 CurrentDomain.GetAllAssemblies() 不是一个好主意,因为并非所有项目程序集都可以在程序启动时加载(某些程序集可以在用户操作或其他事件时加载)。在这种情况下,您将遇到依赖项的空引用异常。

I think that is not a good idea to use CurrentDomain.GetAllAssemblies() because not all project assemblies can be loaded on program startup ( some assemblies can be loaded on user actions for example or other events). In this case you will have null-reference exceptions for dependencies.

转瞬即逝 2024-12-18 18:11:22

您可以使用反射来查找并实例化 Ninject 模块:

BuildManager.GetReferencedAssemblies()
    .Cast<Assembly>()
    .SelectMany(a => a.DefinedTypes)
    .Where(t => typeof(INinjectModule).IsAssignableFrom(t))
    .Select(t => (INinjectModule)Activator.CreateInstance(t))

You can use reflection to find and instantiate the Ninject modules:

BuildManager.GetReferencedAssemblies()
    .Cast<Assembly>()
    .SelectMany(a => a.DefinedTypes)
    .Where(t => typeof(INinjectModule).IsAssignableFrom(t))
    .Select(t => (INinjectModule)Activator.CreateInstance(t))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文