如何在应用程序中组织 DI 框架的使用?

发布于 2025-01-07 16:55:55 字数 730 浏览 4 评论 0原文

编辑:我忘记将内核移至此处的非通用父类并提供虚拟方法来访问它。我确实意识到下面的示例将创建过多的内核实例。

上周我刚刚学会了如何进行注入,以下是我目前的设置方式:

using Ninject;
using System.Reflection;

namespace Infrastructure
{
    public static class Inject<T>
    {
        static bool b = Bootstrap();
        static IKernel kernel;

        static bool Bootstrap()
        {
            kernel = new StandardKernel();
            kernel.Load(Assembly.GetExecutingAssembly());
            return true;
        }

        public static T New() { return kernel.Get<T>(); }
    }
}

然后我计划将各种 ninject 模块类作为基础设施命名空间的一部分,以便加载它们。

我无法在这里或 Google 上找到任何内容来提供有关如何在项目中实际组织 Ninject 的使用的示例,但这对我来说似乎是正确的,因为它允许我只需要在此程序集中引用 Ninject。这是或多或少“正确”的方式还是有更好的设计?

EDIT: I forgot to move the kernel into a non-generic parent class here and supply a virtual method to access it. I do realize that the example below, as is, would create a plethora of kernel instances.

I just learned how to do injection this past week and here's how I've got things set up currently:

using Ninject;
using System.Reflection;

namespace Infrastructure
{
    public static class Inject<T>
    {
        static bool b = Bootstrap();
        static IKernel kernel;

        static bool Bootstrap()
        {
            kernel = new StandardKernel();
            kernel.Load(Assembly.GetExecutingAssembly());
            return true;
        }

        public static T New() { return kernel.Get<T>(); }
    }
}

And then I plan to make the various ninject module classes part of the Infrastructure namespace so that this will load them.

I haven't been able to find anything on here or Google that gives examples of how to actually organize the usage of Ninject in your project, but this seems right to me as it allows me to only need the Ninject reference in this assembly. Is this a more or less 'correct' way or is there a better design?

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

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

发布评论

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

评论(1

远山浅 2025-01-14 16:55:55

您现在的做事方式存在一些问题。

首先让我从明显的 C# 问题开始:泛型类中的静态类变量是在每个 T 基础上共享的。换句话说, InjectInject 将各自获得自己的 IKernel 实例,这不太可能是您真正想要的,因为您很可能在应用程序的生命周期内需要一个 IKernel。当您的应用程序没有单个 IKernel 时,就无法将类型注册为单例,因为单例的作用域始终是容器级别,而不是应用程序级别。因此,您最好将该类重写为非泛型,并将泛型类型参数移至该方法:

Inject.New<T>()

第二个问题是有关依赖项注入的问题。在我看来,您正在尝试使用 服务定位器反模式 ,因为您可能在应用程序中显式调用 Inject.New 。 DI 容器只能在应用程序的启动路径中被引用,并且应该能够构建相关对象的完整对象图。通过这种方式,您可以要求容器为您获取根级对象(例如 MVC 上下文中的控制器),而应用程序的其余部分将不会注意到任何 DI 技术的使用。当您执行此操作时,无需抽象容器的使用(就像您对 Inject 类所做的那样)。

顺便说一句,并非所有应用程序或 UI 技术都允许这样做。在使用 Web 窗体应用程序时,我倾向于隐藏我的容器(就像您所做的那样),因为不可能对 Page 类、IHttpHandler 对象进行正确的依赖项注入和 UserControl 类。

There are a few problems with how you are doing things now.

Let me first start with the obvious C# problem: Static class variables in generic classes are shared on a per T basis. In other words, Inject<IUserRepository> and Inject<IOrderRepository> will each get their own IKernel instance, which is unlikely what you really want, since it is most likely you need a single IKernel for the life time of your application. When you don't have a single IKernel for the application, there is no way to register types as singleton, since singleton is always scoped at the container level, not at the application level. So, you better rewrite the class as non-generic and move the generic type argument to the method:

Inject.New<T>()

The second problem is one concerned dependency injection. It seems to me you are trying to use the Service Locator anti-pattern, since you are probably explicitly calling Inject.New<T> from within your application. A DI container should only be referenced in the start-up path of the application and should be able to construct a complete object graph of related objects. This way you can ask the container to get a root level object for you (for instance a Controller in the context of MVC) and the rest of the application will be oblivious to the use of any DI technology. When you doing this, there is no need to abstract the use of the container away (as you did with your Inject class).

Not all application or UI technologies allow this BTW. I tend to hide my container (just as you are doing) when working with a Web Forms application, because it is impossible to do proper dependency injection on Page classes, IHttpHandler objects, and UserControl classes.

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