Asp.net MVC源码分析--DependencyResolver与Service Location
这一篇我们讲解如何利用DependencyResolver来定位我们的自定义服务(service)也就查找Controller.
首先让我们来看一下DependencyResolver 的实现。
DependencyResolver.cs
1 public class DependencyResolver {
2 // Static accessors
3
4 private static DependencyResolver _instance = new DependencyResolver();
5
6 public static IDependencyResolver Current {
7 get {
8 return _instance.InnerCurrent;
9 }
10 }
11
12 public static void SetResolver(IDependencyResolver resolver) {
13 _instance.InnerSetResolver(resolver);
14 }
15
16 public static void SetResolver(object commonServiceLocator) {
17 _instance.InnerSetResolver(commonServiceLocator);
18 }
19
20 [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types.")]
21 public static void SetResolver(Func<Type, object> getService, Func<Type, IEnumerable<object>> getServices) {
22 _instance.InnerSetResolver(getService, getServices);
23 }
24
25 // Instance implementation (for testing purposes)
26
27 private IDependencyResolver _current = new DefaultDependencyResolver();
28
29 public IDependencyResolver InnerCurrent {
30 get {
31 return _current;
32 }
33 }
34
35 private class DefaultDependencyResolver : IDependencyResolver {
36 [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "This method might throw exceptions whose type we cannot strongly link against; namely, ActivationException from common service locator")]
37 public object GetService(Type serviceType) {
38 try {
39 return Activator.CreateInstance(serviceType);
40 }
41 catch {
42 return null;
43 }
44 }
45
46 public IEnumerable<object> GetServices(Type serviceType) {
47 return Enumerable.Empty<object>();
48 }
49 }
50 }
51
52
DependencyResolver.Current 默认返回的是DefaultDependencyResolver 类型的实例,在这个类中我们看到它实现了IDependencyResolver.GetService 接口, 这个实现是调用了Activator.CreateInstance(serviceType); 返回一个类型的实例。
这里框架为我们提供了一个时点使我们可以调用DependencyResolver.SetResolver方法来注入我们自己的IDependencyResolver的实现。
---------------------------------------------------------------------------------------------
接下来我们看MvcHandler,所有的Request请需要在这里查找我们的Controller,在这个类的ProcessRequestInit方法中我们可以看到它调用了ControllerBuilder.GetControllerFactory(); 先找到Controller的工成类实例IControllerFactory,再调用它的CreateController方法来寻找和创建Controller.
MvcHandler.cs
1 private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory) {
2 // If request validation has already been enabled, make it lazy. This allows attributes like [HttpPost] (which looks
3 // at Request.Form) to work correctly without triggering full validation.
4 bool? isRequestValidationEnabled = ValidationUtility.IsValidationEnabled(HttpContext.Current);
5 if (isRequestValidationEnabled == true) {
6 ValidationUtility.EnableDynamicValidation(HttpContext.Current);
7 }
8
9 AddVersionHeader(httpContext);
10 RemoveOptionalRoutingParameters();
11
12 // Get the controller type
13 string controllerName = RequestContext.RouteData.GetRequiredString("controller");
14
15 // Instantiate the controller and call Execute
16 factory = ControllerBuilder.GetControllerFactory();
17 controller = factory.CreateController(RequestContext, controllerName);
18 if (controller == null) {
19 throw new InvalidOperationException(
20 String.Format(
21 CultureInfo.CurrentCulture,
22 MvcResources.ControllerBuilder_FactoryReturnedNull,
23 factory.GetType(),
24 controllerName));
25 }
26 }
-------------------------------------------------------------------------------------------
下面我们看一下ControllerBuilder类,看一下它是如何工作的。
ControllerBuilder.cs
在构造函数中我们看到它初始化了_serviceResolver 变量,它的类型是SingleServiceResolver<IControllerFactory>,在它初始化时传入了_factoryThunk(返回值为空的委托),和DefaultControllerFactory实例。接下来我们看一下SingleServiceResolver的实现。
SingleServiceResolver.cs
1 internal class SingleServiceResolver<TService> : IResolver<TService> where TService : class {
2
3 private TService _currentValueFromResolver;
4 private Func<TService> _currentValueThunk;
5 private TService _defaultValue;
6 private Func<IDependencyResolver> _resolverThunk;
7 private string _callerMethodName;
8
9 public SingleServiceResolver(Func<TService> currentValueThunk, TService defaultValue, string callerMethodName) {
10 if (currentValueThunk == null) {
11 throw new ArgumentNullException("currentValueThunk");
12 }
13 if (defaultValue == null) {
14 throw new ArgumentNullException("defaultValue");
15 }
16
17 _resolverThunk = () => DependencyResolver.Current;
18 _currentValueThunk = currentValueThunk;
19 _defaultValue = defaultValue;
20 _callerMethodName = callerMethodName;
21 }
22
23 internal SingleServiceResolver(Func<TService> staticAccessor, TService defaultValue, IDependencyResolver resolver, string callerMethodName)
24 : this(staticAccessor, defaultValue, callerMethodName) {
25 if (resolver != null) {
26 _resolverThunk = () => resolver;
27 }
28 }
29
30 public TService Current {
31 get {
32 if (_resolverThunk != null) {
33 lock (_currentValueThunk) {
34 if (_resolverThunk != null) {
35 _currentValueFromResolver = _resolverThunk().GetService<TService>();
36 _resolverThunk = null;
37
38 if (_currentValueFromResolver != null && _currentValueThunk() != null) {
39 throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, MvcResources.SingleServiceResolver_CannotRegisterTwoInstances, typeof(TService).Name.ToString(), _callerMethodName));
40 }
41 }
42 }
43 }
44 return _currentValueFromResolver ?? _currentValueThunk() ?? _defaultValue;
45 }
46 }
47 }
我们看到
_resolverThunk = () => DependencyResolver.Current;//这里就为我们注入自己的ControllerFactory提供机会_currentValueFromResolver = _resolverThunk().GetService<TService>();我们知道框架使用了DependencyResolver.Current来提供GetService的功能,如果没有则返回默认的DefaultControllerFactory实例(从构造函数中传入)。
--------------------------------------------------------------------------------------------
接下来我们看DefaultControllerFactory的实现,
1 public class DefaultControllerFactory : IControllerFactory {
2 public DefaultControllerFactory()
3 : this(null, null, null) {
4 }
5
6 public DefaultControllerFactory(IControllerActivator controllerActivator)
7 : this(controllerActivator, null, null) {
8 }
9
10 internal DefaultControllerFactory(IControllerActivator controllerActivator, IResolver<IControllerActivator> activatorResolver, IDependencyResolver dependencyResolver) {
11 if (controllerActivator != null) {
12 _controllerActivator = controllerActivator;
13 }
14 else {
15 _activatorResolver = activatorResolver ?? new SingleServiceResolver<IControllerActivator>(
16 () => null,
17 new DefaultControllerActivator(dependencyResolver),
18 "DefaultControllerFactory contstructor"
19 );
20 }
21 }
22
23 private IControllerActivator ControllerActivator {
24 get {
25 if (_controllerActivator != null) {
26 return _controllerActivator;
27 }
28 _controllerActivator = _activatorResolver.Current;
29 return _controllerActivator;
30 }
31 }
32
33 public virtual IController CreateController(RequestContext requestContext, string controllerName) {
34 if (requestContext == null) {
35 throw new ArgumentNullException("requestContext");
36 }
37 if (String.IsNullOrEmpty(controllerName)) {
38 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "controllerName");
39 }
40 Type controllerType = GetControllerType(requestContext, controllerName);
41 IController controller = GetControllerInstance(requestContext, controllerType);
42 return controller;
43 }
44
45 protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType) {
46
47 return ControllerActivator.Create(requestContext, controllerType);
48 }
49
50
51
52 private class DefaultControllerActivator : IControllerActivator {
53 Func<IDependencyResolver> _resolverThunk;
54
55 public DefaultControllerActivator()
56 : this(null) {
57 }
58
59 public DefaultControllerActivator(IDependencyResolver resolver) {
60 if (resolver == null) {
61 _resolverThunk = () => DependencyResolver.Current;
62 }
63 else {
64 _resolverThunk = () => resolver;
65 }
66 }
67
68 public IController Create(RequestContext requestContext, Type controllerType) {
69 try {
70 return (IController)(_resolverThunk().GetService(controllerType) ?? Activator.CreateInstance(controllerType));
71 }
72 catch (Exception ex) {
73 throw new InvalidOperationException(
74 String.Format(
75 CultureInfo.CurrentCulture,
76 MvcResources.DefaultControllerFactory_ErrorCreatingController,
77 controllerType),
78 ex);
79 }
80 }
81 }
82 }
83 }
在这个类中我们同样看到了和ControllerBuilder中一样的模式,也是利用SingleServiceResolver,来初始化IControllerActivator实例。如果在DependencyResolver.Current中没有找到IControllerActivator类型的话使用DefaultControllerActivator.最终利用DefaultControllerActivator.Create方法创建Controller的实例。
这里框架又提供了一个时点让我们注册自已实现的IControllerActivator类。
总结:
DependencyResolver 与SingleServiceResolver/MutiServiceResolver 在MVC框架中配合使用的。
只要用到了ServiceResolver的地方,我们都可能通过在DependencyResolver 注册自己的行为从而改变框架的行为。
口渴中。。www.2cto.com
不知道说清楚没,下一篇我们分析Ninject.MVC 与asp.net MVC 的集成。
相关新闻>>
- 发表评论
-
- 最新评论 更多>>