Asp.net MVC源码分析--DependencyResolver与Service Location

来源:未知 责任编辑:智问网络 发表时间:2013-10-07 01:00 点击:

 

这一篇我们讲解如何利用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 的集成。

 


摘自 十一月的雨
    发表评论
    请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
    用户名: 验证码:点击我更换图片
    最新评论 更多>>

    推荐热点

    • 浅析.NET下XML数据访问新机制
    • asp.net 面试+笔试题目第1/2页
    • C# 邮件地址是否合法的验证
    • C#高级编程:数据库连接[1]
    • asp.net 设置GridView的选中行的实现代码
    • 经典C++程序1
    • IIS 自动回收导致后台定时器失效的问题解决
    • ASP.NET&#160;GridView列表代码示例
    • 微软ASP.NET站点部署指南(3):使用Web.Config文件的Transforma
    网站首页 - 友情链接 - 网站地图 - TAG标签 - RSS订阅 - 内容搜索
    Copyright © 2008-2015 计算机技术学习交流网. 版权所有

    豫ICP备11007008号-1