Asp.net MVC 通过自定义ControllerFactory实现构造器注入
一、重写ControllerFactory的GetControllerInstance
ControllerFactory是asp.net中用于在运行时构造Controller的工厂 ,默认使用的工厂在构造Controller时,默认调用Controller的无参构造函数,所以要实现构造器注入,需要重写工厂中构造Controller的方法GetControllerInstance:
1 public class CustomControllerFactory : DefaultControllerFactory 2 { 3 protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext,Type controllerType) 4 { 5 //获取构造函数对象 6 var constructor = controllerType.GetConstructors()[0]; 7 //获取构造函数参数 8 var param = constructor.GetParameters(); 9 //获取构造函数所需的参数 10 var paramNames = param.Select(a => { 11 var serviceType = (ServiceAttribute)(a.ParameterType.GetCustomAttributes(typeof(ServiceAttribute), true)[0]); 12 var t = Type.GetType(serviceType.ServiceName + ", " + serviceType.ServiceNameSpace, true); 13 return Activator.CreateInstance(t); 14 }).ToArray(); 15 IController controller = Activator.CreateInstance(controllerType, paramNames) as Controller; 16 return controller; 17 } 18 }
在获取构造函数参数的时候,需要让发射机制寻找到服务的程序集,所以在这个地方我定义了一个名为Service的特性:
1 public class ServiceAttribute : Attribute 2 { 3 private string _serviceName; 4 private string _serviceNamespace; 5 public ServiceAttribute(string serviceName, string serviceNamespace) 6 { 7 _serviceName = serviceName; 8 _serviceNamespace = serviceNamespace; 9 } 10 11 public string ServiceName 12 { 13 get { return _serviceName; } 14 } 15 16 public string ServiceNameSpace 17 { 18 get { return _serviceNamespace; } 19 } 20 }
二、定义服务接口:
1 [Service(serviceName: "InjectController.Service.Impl.AddService", serviceNamespace: "InjectController.Service.Impl")] 2 public interface IAddService 3 { 4 int Add(int a, int b); 5 }
serviceName是服务的全称,serviceNamespace是服务的命名空间。
三、继承服务接口并实现:
1 public class AddService:IAddService 2 { 3 public int Add(int a, int b) 4 { 5 return a + b; 6 } 7 }
四、在Controller中定义构造函数,引用服务接口
1 public class HomeController : Controller 2 { 3 private ILoggerService _loggerService; 4 private IAddService _addService; 5 public HomeController(ILoggerService loggerService,IAddService addService) 6 { 7 _loggerService = loggerService; 8 _addService = addService; 9 } 10 11 public ActionResult Index(int num1, int num2) 12 { 13 _loggerService.Logger(num1.ToString() + "+" + num2.ToString() + "=" + _addService.Add(num1,num2).ToString() + " " + "\r\n"); 14 return View("Index", new LoggerDTO() { LoggerContent = _loggerService.GetLogger() }); 15 } 16 }
ILoggerService没有在文章中列出,其格式与IAddService相同。
五、在Global.asax中重新注册控制器工厂,覆盖默认的构造器工厂:
1 public class MvcApplication : System.Web.HttpApplication 2 { 3 protected void Application_Start() 4 { 5 AreaRegistration.RegisterAllAreas(); 6 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 7 RouteConfig.RegisterRoutes(RouteTable.Routes); 8 BundleConfig.RegisterBundles(BundleTable.Bundles); 9 10 RegisterCustomControllerFactory(); 11 } 12 13 private void RegisterCustomControllerFactory() 14 { 15 IControllerFactory factory = new CustomControllerFactory(); 16 ControllerBuilder.Current.SetControllerFactory(factory); 17 } 18 }
运行:发现接口成功的在构造函数中被注入