如何组织应用程序中DI框架的使用? [英] How to organize DI Framework usage in an application?

查看:105
本文介绍了如何组织应用程序中DI框架的使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我忘了在这里将内核移到非通用父类中,并提供了一个虚拟方法来访问它.我确实意识到,下面的示例将创建大量的内核实例.

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

然后我计划使各种ninject模块类成为基础结构名称空间的一部分,以便将其加载.

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

我在这里或Google上都找不到任何可以实际组织项目中Ninject用法的示例,但这对我来说似乎是正确的,因为它使我只需要在此使用Ninject参考即可部件.这是一种或多或少的正确"方式,还是有更好的设计?

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?

推荐答案

您现在的处事方式存在一些问题.

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

让我首先从一个明显的C#问题开始:泛型类中的静态类变量按每个T共享.换句话说,Inject<IUserRepository>Inject<IOrderRepository>将各自获得自己的IKernel实例,这不太可能是您真正想要的,因为在应用程序的整个生命周期中,很可能只需要一个IKernel即可.如果应用程序没有单个IKernel,则无法将类型注册为单例,因为单例始终在容器级别而不是在应用程序级别范围内.因此,最好将类重写为非泛型并将泛型类型参数移至方法:

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

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

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).

并非所有应用程序或UI技术都允许该BTW.在使用Web Forms应用程序时,我倾向于隐藏我的容器(就像您所做的一样),因为不可能对Page类,IHttpHandler对象和UserControl类进行适当的依赖注入.

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.

这篇关于如何组织应用程序中DI框架的使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆