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     }

 

运行:发现接口成功的在构造函数中被注入

posted on 2016-11-28 16:19  Kakura  阅读(3933)  评论(2编辑  收藏  举报

导航