IoC容器,检查在编译时错误 [英] IoC container, check for errors at compile time

查看:159
本文介绍了IoC容器,检查在编译时错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的问题。

让我们说我有一个.NET解决方案,与不同的项目像一些类库(BLL,DAL等),它可以是一个Web应用程序或WPF应用程序,也没关系主要项目。

Let's say I have a .Net solution, with different projects like some class libraries (bll, dal, etc) and a main project which can be a web application or a wpf application, it doesn't matter.

现在,让我们说,我想使用IoC容器(如温莎,Ninject,团结等)来解决这样的东西验证,仓库,通用的接口实现和这样的。

Now let's say I want to use an IoC container (like Windsor, Ninject, Unity, etc) to resolve stuff like validators, repositories, common interface implementations and such.

我把它放在一起。编译并运行良好。然后,有一天,我添加了一个新的服务,并在我的code我只是试图通过IoC容器来解决这个问题。事情是,我忘记在IOC配置进行注册。

I put it all together. Compiles and runs fine. Then, someday, I add a new service, and in my code I just try to resolve it through the IoC container. Thing is, I forget to register it in the IoC configuration.

一切编译,并且将应用程序部署并运行。一切工作正常,除了当一个页面的code要求提供新的服务,容器,容器的回答哎,我不知道这个服务什么。

Everything compiles, and the application gets deployed and runs. All works fine, except for when a page's code asks for that new service to the container, and the container answers "hey, I don't know anything about this service".

您获得您的错误记录,以及用户友好的错误页面。你会去检查错误,看到问题并解决它。 pretty的标准。

You get your error logged, and the user friendly error page. You'll go check the error, see the problem and fix it. Pretty standard.

现在,让我们说,我们要提高的过程,并以某种方式可以知道在编译时,如果我们期望IoC容器来处理每一个服务都在code正确注册。

Now let's say we want to improve the process, and in some way be able to know at compile time if every service that we expect the IoC container to handle is registered correctly in the code.

这怎么可能实现?有一件事,单元测​​试是从可能的答案排除,我正在寻找另一种方式,如果它确实存在。

How could this be achieved? One thing, Unit Tests are ruled out from possible answers, I'm looking for another way, if it does exist.

思考?

编辑 - 一些答案和意见后,似乎单元测试确实是实现此功能的唯一方法

EDIT - After some answers and comments, it seems that Unit Tests are indeed the only way to achieve this feature.

我想知道的是,如果单元测试是 - 以任何理由 - 不可能的,因此,国际奥委会不能在编译时间的考验,将这项$ P $使用IoC容器,并选择了pvent您直接实例在你的code?我的意思是,你会认为太不安全和冒险使用国际奥委会和后期绑定,并看到它的优势被打出这个漏洞?

What I'd like to know is, if Unit Tests were - for any reason - not possible, and thus IoC could not be tested at compiled time, would this prevent you from using an IoC container and opting for direct instantiation all over your code? I mean, would you consider too unsafe and risky to use IoC and late binding, and see its advantages being outscored by this "flaw"?

推荐答案

这是不可能的编译器来验证你的整个程序的工作。你的程序编译的事实,但这并不意味着它正常工作(即使不使用IOC)。为此,你需要两个自动化测试和手动测试。这并不意味着你不应该试图让编译器做的那么多,因为它可以,但远离国际奥委会的理由是不好的,因为国际奥委会是为了让您的应用程序灵活,可测试性和可维护性。如果没有国际奥委会你将不能够正确地测试code,且无任何自动化测试中,它几乎是不可能写出任何合理规模的维护的软件。

It is impossible for the compiler to validate the working of your whole program. The fact that your program compiles, doesn't mean it works correctly (even without using IoC). For that you'll need both automated tests and manual testing. This doesn't mean that you shouldn't try to let the compiler do as much as it can, but staying away from IoC for that reason is bad, since IoC is meant to keep your application flexible, testable and maintainable. Without IoC you won't be able to test your code properly, and without any automated tests it is almost impossible to write any reasonably sized maintainable software.

具有灵活性,但是国际奥委会规定,并不意味着依赖一些特定的一块code有,不能再由编译器验证。所以,你需要做到这一点的另一种方式。

Having the flexibility as IoC provides however, does mean that the dependencies some particular piece of code has, can't be validated anymore by the compiler. So you need to do this in another way.

有些DI框架,以查证容器的正确性。 简单的喷油器例如,包含验证()的方法,这将简单地遍历所有注册和解析实例为每个注册。通过调用这个方法(或使用类似的方法)在应用程序启动时,你会发现在(开发商)的测试,如果事情是错的DI配置,它将prevent应用程序无法启动。你可以在单元测试中,甚至做到这一点。

Some DI frameworks allow you to verify the container for correctness. Simple Injector for instance, contains a Verify() method, that will simply iterate over all registrations and resolve an instance for each registration. By calling this method (or using a similar approach) during application startup, you will find out during (developer) testing if something is wrong with the DI configuration and it will prevent the application from starting. You could even do this in a unit test.

然而重要的是,该测试DI配置应该不需要太多的维护。如果你必须添加一个单元测试您注册验证容器中的每个类型,你会失败,只是因为缺少注册(因此缺少单元测试)将是摆在首位失败的原因。

Important however is, that testing the DI configuration should not need much maintenance. If you must add a unit test for each type that you register to verify the container, you will fail, simply because the missing registration (and thus a missing unit test) will be the reason to fail in the first place.

这让你几乎编译时支持。但是,你必须意识到你的应用程序的设计和连线的东西放在一起的方式。这里有一些提示:

This gives you 'almost' compile-time support. However, you need to be conscious about the design of your application and the way you wire things together. Here are some tips:

  1. 在远离隐性财产注入,其中容器被允许跳过注入的财产,如果它不能找到一个注册的依赖。这将不允许您的应用程序快速失败,将导致的NullReferenceException 秒后上。明确财产注入,在那里你强制容器注入的属性是好的,但是,使用构造器注入只要有可能。
  2. 注册所有根对象明确如果可能的话。例如,明确注册所有的ASP.NET MVC 控制器情况下,在容器中。通过这种方式,容器可以检查从根对象开始完全依赖图。你应该通过使用反射来发现所有的根类型注册的所有根对象以自动方式,例如。简单喷油器实例的 MVC3集成的NuGet包,包含 RegisterMvcControllers 将会为你做这个扩展方法。其他容器的整合包包含类似的特征。
  3. 如果注册根对象是不可能或不可行,在启动过程中手动测试创建每一根对象。在ASP.NET Web窗体类的实例,你可能会调用容器从其构造函数中(因为类必须不幸的是有一个默认的构造函数)。在这里再次关键是找到他们全部使用反射一次研究。通过寻找所有的页面类使用反射和实例化他们,你会发现(在应用程序启动或测试时间)是否与您的DI配置还是不成问题的。
  4. 让你的IoC容器管理你有一个公共构造的所有服务。多个构造导致混乱,并且可以打破联合国predictable方式您的应用程序。有多个构造是一个反模式
  5. 在有些情况还不能在应用程序启动时创建一些依赖场景。以确保该应用程序可以被正常启动并去离子的配置的其余部分仍可被验证的,抽象的后面代理或抽象工厂那些依赖关系。
  1. Stay away from implicit property injection, where the container is allowed to skip injecting the property if it can't find a registered dependency. This will disallow your application to fail fast and will result in NullReferenceExceptions later on. Explicit property injection, where you force the container to inject a property is fine, however, use constructor injection whenever possible.
  2. Register all root objects explicitly if possible. For instance, register all ASP.NET MVC Controller instances explicitly in the container. This way the container can check the complete dependency graph starting from the root objects. You should register all root objects in an automated fashion, for instance by using reflection to find all root types. The MVC3 Integration NuGet Package of the Simple Injector for instance, contains a RegisterMvcControllers extension method that will do this for you. Integration packages of other containers contain similar features.
  3. If registering root objects is not possible or feasible, test the creation of each root object manually during startup. With ASP.NET Web Form Page classes for instance, you will probably call the container from within their constructor (since Page classes must unfortunately have a default constructor). The key here again is finding them all in once using reflection. By finding all Page classes using reflection and instantiating them, you'll find out (during app start-up or test time) whether there is a problem with your DI configuration or not.
  4. Let all services that your IoC container manages for you have a single public constructor. Multiple constructors result in ambiguity and can break your application in unpredictable ways. Having multiple constructors is an anti-pattern.
  5. There are scenarios where some dependencies can not yet be created during application start-up. To ensure that the application can be started normally and the rest of the DI configuration can still be validated, abstract those dependencies behind a proxy or abstract factory.

这篇关于IoC容器,检查在编译时错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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