MVC中的扩展点(三)控制器工厂
2018-02-03 16:12
309 查看
当路由系统找到与当前请求匹配的路由信息(
默认情况下,MVC框架使用
从
通过
设想以下情景:领域模型中有个
我们选用NInject开源库来实现DI(下载地址:http://ninject.org/download):
1、下载NInject,并解压
2、新建一个空的MVC工程
3、添加引用Ninject.dll、System.Data.Linq
4、在SQL Server Management Studio Express中附加上源代码中的Test数据库
6、创建一个
ProductsController
7、创建与
8、创建一个控制器工厂:
“`
Ok,要在虚拟产品列表与真实的
注意:本文涉及到有关的
RouteData),而路由信息中的
RouteHandler为
MvcRouteHandler,那么此请求将由
MvcRouteHandler返回的
MvcHandler来负责处理。默认情况下
MvcHandler将根据请求上下文(
RequestContext)中的信息找到对应的控制器和活动方法,通过调用活动方法,返回应答内容,将其返回给客户端。
MvcHandler类通过使用单例类
ControllerBuilder的
GetControllerFactory方法获取当前指定的
IControllerFactory对象,通过此对象来生成具体的
IController控制器。对于
MvcHandler来说,它只关心
IController对象,即只负责调用IController的Execute方法来产生应答内容。
Action方法是MVC框架默认
Controller类中实现的一种机制,它通过路由信息中的action参数来确定调用
Controller类中的某个对应方法,以此产生应答内容。
默认情况下,MVC框架使用
DefaultControllerFactory控制器工厂,它使用路由信息中的
controller参数来确定具体的控制器类,并通过反射机制生成控制器实例。
从
MvcRouteHandler接收到请求到最终确定使用那个控制器,涉及到的类,如下图所示:
通过
ControllerBuilder的
SetControllerFactory方法我们可以指定自定义的控制器工厂,自定义工厂可以直接实现
IControllerFactory接口,也可以从
DefaultControllerFactory类继承,如果直接实现
IControllerFactory,则我们必须自己实现一种机制将路由信息与控制器对应起来。所以为了使用
MVC中默认的路由解析功能,我们通常从
DefaultControllerFactory继承,然后根据实际情况覆写
GetControllerInstance与
GetControllerType方法,其中
GetControllerInstance用于返回一个IController控制器,
GetControllerType用于根据路由信息获取合适的控制器类型。显然,在默认控制器工厂中,
CreateController方法先调用
GetControllerType找出类型,然后调用
GetControllerInstance方法创建一个控制器实例。
DefaultControllerFactory使用
Activator.CreateInstance方法来创建控制器对象,所以
MVC默认的控制器必须具有无参构造函数。下面我们使用依赖注入(DI)技术使我们的自定义控制器工厂具有实例化有参控制器。
设想以下情景:领域模型中有个
Product类,我们为其定义了一个
IProductsRepository的存储管理类。首先,我们实现了一个
SqlProductsRepository类,用于从
SqlServer数据库中获取产品资料,然后,为方便测试,我们还实现了一个
MockProductsRepository类,用于返回一个简单的产品列表。我们建立一个
ProductsController控制器,为确定使用哪种存储实现,我们要求在生成控制器实例时,必须传入一个
IProductsRepository对象:
我们选用NInject开源库来实现DI(下载地址:http://ninject.org/download):
1、下载NInject,并解压
2、新建一个空的MVC工程
3、添加引用Ninject.dll、System.Data.Linq
4、在SQL Server Management Studio Express中附加上源代码中的Test数据库
5、按上述类图实现各个接口及类
6、创建一个
ProductsController,增加一个带
IProductsRepository参数的构造函数
ProductsController
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace CnBlogs.ControllerFactory.Controllers { public class ProductsController : Controller { private IProductsRepository _repository; public ProductsController(IProductsRepository repository) { _repository = repository; } public ActionResult Index() { return View(_repository.GetProductsList()); } } }
7、创建与
Index Action方法对应的视图
Index.aspx
8、创建一个控制器工厂:
NinjectControllerFactoryNinjectControllerFactory
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using Ninject.Modules; using Ninject; using CnBlogs.ControllerFactory.Models; using System.Configuration; namespace CnBlogs.ControllerFactory.Infrastructure { public class NinjectControllerFactory : DefaultControllerFactory { private IKernel _kernel = new StandardKernel(new MyModule()); protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) { if (controllerType == null) return null; return (IController)_kernel.Get(controllerType); } private class MyModule : NinjectModule { public override void Load() { //Bind<IProductsRepository>() // .To<MockProductsRepository>(); Bind<IProductsRepository>() .To<SqlProductsRepository>() .WithConstructorArgument("connectstring", ConfigurationManager.ConnectionStrings["TestDb"].ConnectionString); } } } } ``` 9、在`Global.asax.cs`中设置自定义工厂
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterRoutes(RouteTable.Routes); ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory()); }
“`
Ok,要在虚拟产品列表与真实的
SqlServer中的产品列表中切换,我们只需修改
MyModule中的
Load方法,将
Controller构造函数中的特定参数绑定到一个具体的实现。
注意:本文涉及到有关的
Linq、DI方面的知识,请参考相关资料。要运行本文示例,请先将源代码中的mdf文件附加到
SqlServer Express中,并修改
App.config中
TestDb连接字符串的定义。
相关文章推荐
- MVC中的扩展点(三)控制器工厂
- MVC扩展控制器工厂,通过继承DefaultControllerFactory来决定使用哪个接口实现,使用Ninject
- MVC中的扩展点(二)控制器工厂
- MVC扩展控制器工厂,通过实现IControllerFactory,根据action名称生成不同的Controller
- Mvc如何重写控制器工厂!
- MVC项目实践,在三层架构下实现SportsStore-03,Ninject控制器工厂等
- ASP.NET MVC 4 (四) 控制器扩展
- ASP.NET MVC 4 (四) 控制器扩展
- ASP.NET MVC 4 (四) 控制器扩展
- MVC扩展控制器, 把部分视图转换成字符串(带验证信息), 并以json传递给前端视图
- MVC项目实践,在三层架构下实现SportsStore-03,Ninject控制器工厂等
- MVC 5 + EF6 完整教程16 -- 控制器详解
- Asp.net MVC Render及Redirect的扩展
- 在 MVC 控制器中使用 构造函数时行依赖注入 (IoC)
- ABP+AdminLTE+Bootstrap Table权限管理系统第六节--abp控制器扩展及json封装以及6种处理时间格式化的方法
- MVC控制器详解
- MVC之控制器
- ASP.NET MVC 5 -从控制器访问数据模型
- ASP.NET MVC自定义路由 - 实现IRouteConstraint限制控制器名(转载)
- MVC 控制器