MVC Controller Dependency Injection for Beginners【翻译】
在codeproject看到一篇文章,群里的一个朋友要帮忙我翻译一下顺便贴出来,这篇文章适合新手,也算是对MEF的一个简单用法的介绍。 Introduction In a simple statement if I want to define an ASP.NET MVC controller then I can say that classes that are responsible for receiving and processing incoming http requests, handling client input, and sending response back to the client. Controllers also act as a coordinator between Model (Business) and View (Presentation). ASP.NET MVC framework itself creates controller objects at run time. There is only one prerequisite, that is controller class must have a parameter less constructor. But if you need to pass some objects with constructor then what will happen? Simply framework will fail to create controller object. In that case we need to create controller objects by our self and inject dependency there. There are many ways you can inject dependency to a class. For example, it might be Property setter,Method, Constructor injection. In this article I will explain how to inject controller dependency to ASP.NET MVC framework with the help of constructor. Without creating custom controller factory inject dependency to controllers are not possible. So I will also explain how to create a very simple custom controller factory and register it to ASP.NET MVC framework. I will also demonstrate a way to inject dependency to controllers using Managed Extensible Framework (MEF). 介绍如果我想用一个简单的声明去定义一个ASP.NET MVC 控制器。然后我会说这个类是负责接收和处理传入的http请求,操作客户端输入,并将响应发送回客户端。Controllers 还可以扮演Model(业务层)和View(表现层)之间的中间人。ASP.NET MVC框架本身在运行时会创建控制器对象。但是有一个前提,那就是控制器类至少必须有一个参数的构造函数。但是,如果你需要传递一些对象给构造函数,那么会发生什么呢?简单的框架,将无法创建控制器对象。在这种情况下,我们需要创建控制器实现自我依赖注入。 有很多方法,你可以注入依赖一类。例如,它可能是物业二传手,方法, 构造函数注入。在这篇文章中,我将解释如何注入控制器的依赖ASP.NET MVC框架的构造函数的帮助。没有创建自定义控制器工厂注入依赖控制器是不可能的。所以,我也将解释如何创建一个非常简单的自定义控制器工厂,并把它注册到ASP.NET MVC框架。我还将展示一种方式来注入依赖使用托管扩展框架(MEF)的控制器。 这里有很多方法可以向类中进行依赖注入。例如,它可能是属性setter方法、构造函数注射。在本文中我将解释向ASP.NETMVC的控制器的使用构造函数辅助进行依赖注入。净MVC框架构造函数的帮助。没有创建自定义控制器工厂注入依赖控制器是不可能的。所以我也会演示如何创建一个非常简单的自定义控制器厂,并把它注册到ASP.NET MVC框架, 我还将演示一种使用托管扩展的框架(MEF)的依赖注入控制器方式。 Why Need to Inject Controller Dependency?In real life application development, you will see almost all ASP.NET MVC applications are needed to inject its dependent component. You can create component directly inside the controller instead of inject them. In that case the controller will be strongly coupled on those components. If any component's implementation is changed or new version of that component is released then you must change controller class itself. Another problem you will face when you will do unit test. You cannot do unit test of those controllers independently (within isolation). You cannot take mocking features from unit testing framework. Without mocking, you cannot do unit test of your code in isolated environment. 在现实生活中的应用程序开发,你会看到,几乎所有的ASP.NET MVC应用程序都需要注入其依赖的组件。您可以在控制器内部创直接建组件对象代替注入。在这种情况下,控制器将被强耦合到这些组件。如果任何组件的实现变更或新版本组件被发布,那么,你必须修改控制器类。当你要做单元测试时,您将面临的另一个问题。 你不能单独对这些控制器类做单元测试。你不能通过单元测试框架实现功能的模拟。没有模拟,你就不能在隔离的环境中做单元测试的代码。 Controller Static StructureASP.NET MVC framework’s controller structure is defined inside an abstract class named Controller. If you want to create any controller, first you will create a class which must be inherited from abstract class 控制器静态结构ASP.NET MVC框架的控制器结构被定义在名为Controller的抽象类。如果你想创建任何控制器,首先您必须必须继承自抽象的Controller类 。Controller类的层次结构的UML类图如下: All controllers root interface is 所有控制器的根接口 Simple Custom Controller DefinitionIf you create an ASP.NET MVC project, you will get two default controllers. One is 简单的自定义控制器定义如果你创建一个ASP.NET MVC项目时,你会得到两个默认控制器。一个是 If you look at the 如果你查看HomeController中类定义,那么你会发现,这个类没有构造函数。 public class HomeController : Controller We all know that if there is no constructor defined then at compile time .NET Framework creates a default parameter-less constructor. 我们都知道,如果没有构造函数的定义,那么在编译的时候,NET Framework会创建一个默认的无参数的构造函数。 public class HomeController : Controller Still I do not find any place where I can create 我仍然没有找到任何地方,在那里我可以在我的代码库创建DefaultLogger对象,我不是自己创建 HomeController的对象,所以我找不到创建 DefaultLogger对象的地方以及如何传递
HomeController 参数给HomeController(ILogger logger)构造函数。如果我生成这个项目,那么,它肯定不会出错。但在运行时将引发异常。 异常详细信息的错误页面将会显示如下:See the stack trace above, object of class
DefaultContollerActivator throw exception named MissingMethodException . If you go MSDN, search the exception which is raised, you will find it there and there clearly mentions “The exception that is thrown when there is an attempt to dynamically access a method that does not exist.” That is the inner exception message. If see next exception named InvalidOperationException , it is actually wrapped MissingMethodException and there you will find more user friendly message and that is “Make sure that the controller has a parameterless public constructor.” If I want to make HomeController workable then I must add a parameter less constructor and framework will create controller object with the help of that constructor. Question will rise how I can pass DefaultLogger object to that controller? Please keep your patience. 查看堆栈跟踪以上,DefaultContollerActivator类的对象 抛出名为MissingMethodException异常 。如果你去MSDN,搜索是谁引发的异常,你会发现它有明确的指出“有一个试图动态访问的方法时不存在引发的异常。”这是内部异常消息。如果看到一个异常名为 InvalidOperationException异常,它实际上是包含MissingMethodException,并且你可以找到更多的友好的提示消息,那就是“确保该控制器具有一个无参数的公共构造函数。”如果我要让 HomeController的可行的话,我必须添加一个无参数的构造函数在框架的帮助下创建控制器对象。问题是,我怎么向控制器传入 DefaultLogger对象?请保持您的耐心。
How MVC Framework Create Controllers?Before start to describe dependency injection process of MVC框架如何创建控制器?开始前描述HomeController的 If you look at the bellow image, you can see that 如果你看看波纹图像,你可以看到, Why Need Custom Controller Factory?Already you know that Default controller factory creates controller object using parameter less constructor. We can inject our controller by parameterless constructor too. See the code below: 为什么需要自定义控制器工厂?你已经知道,默认控制器工厂创建控制器对象使用无参构造函数。我们可的含参的控制器构造函数实现注入。见下面的代码: public class HomeController : Controller I found many developers who are misguided the way of the above dependency injection process. This is not dependency injection at all. This actually clearly violate the dependency inversion principle. The principle say that "High level module should not depend upon the low level module, both should depend on abstraction. Details should depends upon abstraction". In above code HomeController itself create DefaultLogger object. So it directly depends on ILogger implementation (DefaultLogger). If in future another implementation comes of ILogger interface then HomeController code itself need to change. So it is probed that it is not proper way to do. So if we need proper way to inject dependency. We need parameterised constructor, by which we can inject our ILogger component. So current implementation of DefaultControllerFactory does not support this requirement. So we need a new custom controller factory. 我发现许多开发者的错误就是上述依赖注入过程的方式。这根本不是依赖注入。实际上,这显然违反了依赖倒置原则。原则上说,“ 高级别不应依赖于低级别的模块模块,都应该依赖于抽象。细节上都要取决于抽象“。在上面的代码中的HomeController本身创建DefaultLogger对象。因此,它直接取决于ILogger实现(DefaultLogger)。如果在未来有 ILogger接口 的另一种实现,那么HomeController的代码本身需要改变。所以这种尝试是不正确的方式。因此,如果我们需要适当的方式进行注入依赖。我们需要含参构造函数,我们可以注入ILogger组件。因此,当前执行的 DefaultControllerFactory 不支持这一要求。因此,我们需要一个新的自定义控制器工厂。创建自定义控制器厂通过实现 public class CustomControllerFactory : IControllerFactory Now at first you need to register 现在首先你需要在Application_Start方法中向MVC框架注册CustomControllerFactory。 public class MvcApplication : System.Web.HttpApplication If you run the application and see that your parameter-less constructor 如果你运行应用程序会看到无参的HomeController构造函数并没有被调用,含参的 MVC框架调用。哇!你的问题很容易就解决了。You can create your controller creation with little generic way using reflection.
您可以使用反射创建控制器泛型方法
public class CustomControllerFactory : IControllerFactory { first you need to create controller type object from controller full name. Then you create controller object at run time using
首先,您需要从控制器的全名创建控制器类型的对象。然后在运行时使用
Another ApproachAnother way you can create your own controller factory. Though MVC framework’s default implementation of 另一种方法另一种方法,你可以创建自己的控制器工厂。虽然MVC框架的默认实现 public class CustomControllerFactory : DefaultControllerFactory Just create my own 只要继承自 DefaultControllerFactory和重写 GetControllerInstance方法实现自定义逻辑就可以创建自己的CustomControllerFactory类。 MEF for Creating Custom Controller FactoryIn real life project you will see experts are using IOC containers inside controller factory for creating/fetching the MEF创建自定义控制器工厂在现实生活中,您将看到专业的项目在控制器工厂内部使用的是Ioc容器创建/读取Controller对象的。如果您尝试动态创建依赖对象和控制器对象会引发很多 问题。因此,这将是更好的方法在您的项目使用任意的IOC容器到并注册所有的依赖对象。您可以使用各种流行的IOC容器,如Castle Windsor, Unity, NInject, StructureMap etc.等,在这种情况下我将演示如何使用托管扩展框架(MEF)。MEF并不是一个IOC容器。它是一种层组合。你也可以叫它可插拔的框架,在运行时,你可以插入你的依赖组件。几乎所有IOC的工作都可以由MEF完成。采用MEF还是IOC这取决于你应用架构的要求。我的建议是,当你需要在运行时修改你的组件时(运行时间插件在运行),在这种情况下,您可以使用MEF,当您创建组件以及依赖于它的静态引用的组件,那么你可以使用IOC。有很多网上公布文章,哪里可以找到有关的更多详细信息/技术文章。我希望你能多学习,那么当你使用时很容易地作出决定。顺便说一下MEF来自.NET 4.0框架,因此,主要的好处是,不存在第三方组件的依赖。首先,你需要在你的您的项目引用system.ComponentModel.Composition。 Then you create custom Controller Factory. The name of the controller factory is 接下来创建自定义控制器工厂----- public class MefControllerFactory : DefaultControllerFactory
这里的CompositContainer对象是很像IOC容器。内部GetControllerInstance方法用于获取取控制器对象。如果发现空值,那么返回默认的控制器(基类)的对象,否则返回 CompositContainer对象。在创建MefControllerFactory 类,我们需要在在Application Start事件将其注册到MVC 框架。 protected void Application_Start() I use MEF的 InheritedExportAttribute ExportAttribute, PartCreationPolicyAttribute 到接口 ILogger , HomeController
Based on these attributes MEF framework create objects. Just one important think you should remember that when you will use MEF, you should decorate your controllers through 基于这些属性MEF框架创建对象。只是一个重要的知识点你应该记住,当你将使用MEF,你应该装饰你的控制器通过PartCreationPolicyAttribute 并为控制器创建的每个请求策略的对象设置生命周期 [PartCreationPolicy(CreationPolicy.NonShared)], 如果没有就会报错。默认情况下,它将使用SharedCreation策略。
Points of InterestI tried to explain various ways to create controller factory and inject its dependency in a very simple and straight forward way. First and second approach is just make understandable to the process of building and injecting controller and its dependency. You should not use that approach directly to the real life application. You can take IOC or MEF framework for that. You can do more research on MEF and learn MEF usage and best practices after that you will use it to your real life projects. Near future I have a plan to write another article that will demonstrate to use of various IOC containers like Windsor, Unity, NInject, StrucutureMap etc. to inject controller dependency injection and a comparative study with them. In my sample downloadable code I used visual studio 2012 with .NET framework 4.5. Anyone can download and play with that. 亮点我试图解释各种不同的方法来创建一个非常简单直观的注入依赖的控制器的工厂方法。这两种方法是要理解构造和控制器的依赖注入过程。你不应该将其直接应用与真实的项目中。你可以使用IOC或MEF框架。你可以做更多的研究和学习使用MEF及最佳做法之后,可以将它应用到你的现实生活中的项目。不久,我计划写一篇文章,将展示使用多种IoC容器像Windsor, Unity, NInject, StrucutureMap etc.等注入控制器依赖注入并进行比较和研究。 在我的示例下载的代码,我用的是Visual Studio 2012 .NET Framework 4.5。任何人都可以下载玩一玩。 |
MVC Controller Dependency Injection for Beginners【翻译】的更多相关文章
- [转载][翻译] IoC 容器和 Dependency Injection 模式
原文地址:Inversion of Control Containers and the Dependency Injection pattern 中文翻译版本是网上的PDF文档,发布在这里仅为方便查 ...
- 依赖注入 | Dependency Injection
原文链接: Angular Dependency Injection翻译人员: 铁锚翻译时间: 2014年02月10日说明: 译者认为,本文中所有名词性的"依赖" 都可以理解为 & ...
- C# Ioc ASP.NET MVC Dependency Injection
ASP.NET MVC Dependency Injection 同志们,非常快速的Ioc注册接口和注入Mvc Controller,步骤如下: 安装Unity.Mvc NuGet Package 在 ...
- Dependency Injection in ASP.NET MVC
原文引自http://www.dotnetcurry.com/ShowArticle.aspx?ID=786 1.传统三层结构,相邻两层之间交互: 2.如果使用EntityFramework则View ...
- 【译】Dependency Injection with Autofac
先说下为什么翻译这篇文章,既定的方向是架构,然后为了学习架构就去学习一些架构模式.设计思想. 突然有一天发现依赖注入这种技能.为了使得架构可测试.易维护.可扩展,需要架构设计为松耦合类型,简单的说也就 ...
- 【转】dependency injection 的例子
Dependency Injection in PHP. Create your own DI container. / blog / PHP By my opinion one of the big ...
- asp.net core 系列之Dependency injection(依赖注入)
这篇文章主要讲解asp.net core 依赖注入的一些内容. ASP.NET Core支持依赖注入.这是一种在类和其依赖之间实现控制反转的一种技术(IOC). 一.依赖注入概述 1.原始的代码 依赖 ...
- Ninject学习(一) - Dependency Injection By Hand
大体上是把官网上的翻译下而已. http://www.ninject.90iogjkdcrorg/wiki.html Dependency Injection By Hand So what's Ni ...
- Inversion of Control Containers and the Dependency Injection pattern(转)
In the Java community there's been a rush of lightweight containers that help to assemble components ...
随机推荐
- ARM学习 之 如何在向内核写入系统调用
本文主要介绍两个例子:1-系统调用打印“hello kernel” 2-驱动开发板的蜂鸣器 使用的是友善之臂(Friendly ARM)的开发板,三星2440 =================== ...
- Web Analytics 2.0 中文翻译 [ 系列索引 ]
引言 内容概述 第一章:网站分析2.0的新奇世界 第二章:选择你的网络分析灵魂伴侣的最佳策略 第三章:点击流分析的奇妙世界:指标 第四章:点击流分析的奇妙世界:实际的解决方案 第五章:荣耀之钥:度量成 ...
- 认识和使用NSOperation
原文链接:http://www.jianshu.com/p/2de9c776f226 NSOperation是OC中多线程技术的一种,是对GCD的OC包装.它包含队列(NSOperationQueue ...
- grafana日志分析界面及导出的json文件
日志分析面板导出的json文件,效果图如下: 下载地址:http://files.cnblogs.com/files/xiaoming279/%E9%9D%A2%E6%9D%BF.zip 主机面板 主 ...
- ImageView的常用属性
ImageView的一些常用属性,并且这些属性都有与之对应的getter.setter方法: android:adjustViewBounds:设置ImageView是否调整自己的边界来保持所显示图片 ...
- js中join和split的用法
- golang笔记——map
通过 new 创建的引用类型对象是不完整创建,比如 map,它仅分配了字典类型本身所需的内存(指针包装),而没有分配键值存储内存,也没有初始化散列桶等内部属性,因此无法工作,如下代码就是错误的: p ...
- 不要在控制台上使用 let/const
考虑下面的这三句代码和对应的报错信息: 假设写这个代码的人一开始不知道 ES6 里新增的构造函数不能省略 new,于是第一行写错了.然后第二行尝试重新声明一次,结果又报错说重复声明了.那干脆不声明,直 ...
- [原创]Linq to xml增删改查Linq 入门篇:分分钟带你遨游Linq to xml的世界
本文原始作者博客 http://www.cnblogs.com/toutou Linq 入门篇(一):分分钟带你遨游linq to xml的世界 本文原创来自博客园 请叫我头头哥的博客, 请尊重版权, ...
- openjdk 完全编译指南
从openjdk.java.net下载openjdk的软件包,你就获得了所有相关的源码. 强烈建议首先仔细看懂 README-builds.html 指南. 在执行 make all 之前,首先要 执 ...