一、重寫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 }
運行:發現接口成功的在構造函數中被注入