• ASP.NET MVC 中的IResolver<T> 接口


          在ASP.NET MVC 的源码一些实体对象(比如 ControllerBuilder,ControllerFactory, Filters, ViewEngines 等)不再直接通过关键字new来创建实体,而是委托到 IResolver接口,而且 IResolver接口本身也比较简单,这样也提高了框架的可扩展性。由于IResolver<T>是internal,因此不会对外暴漏,在外边应该程序中是不能调用到的。

     internal interface IResolver<T>
     {
            T Current { get; }
     }

        在源码中实现了IResolver接口有2个类,SingleServiceResolver 和MultiServiceResolver ,用的最多的主要是SingleServiceResolver 类

       

     internal class SingleServiceResolver<TService> :IResolver<TService>  where TService : class
     {
        .......
        public TService Current
        {
           get { return _currentValueFromResolver.Value ?? _currentValueThunk() ?? _defaultValue; }
        }
        .......
      }
    

       在SingleServiceResolver实现接口的方法很简单,这这段代码中_currentValueFromResolver,_currentValueThunk,_defaultValue 字段的赋值都是在SingleServiceResolver构造函数中。

         

     public SingleServiceResolver(Func<TService> currentValueThunk, TService defaultValue, string callerMethodName)
     {
         if (currentValueThunk == null){ throw new ArgumentNullException("currentValueThunk");}
         if (defaultValue == null){ throw new ArgumentNullException("defaultValue");}
          _resolverThunk = () => DependencyResolver.Current;
          _currentValueFromResolver = new Lazy<TService>(GetValueFromResolver);
          _currentValueThunk = currentValueThunk;
         _defaultValue = defaultValue;
          _callerMethodName = callerMethodName;
     }
     private TService GetValueFromResolver()
     {
        TService result = _resolverThunk().GetService<TService>();
        if (result != null && _currentValueThunk() != null){
           throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, MvcResources.SingleServiceResolver_CannotRegisterTwoInstances, typeof(TService).Name.ToString(),
    _callerMethodName));
    } return result; }

          在构造函数中_currentValueFromResolver = new Lazy<TService>(GetValueFromResolver)中构造了 Lazy<T> 类的新实例,参数为返回值为TService的委托GetValueFromResolver方法_currentValueThunk  也是一个返回值为TService的委托方法,_defaultValue 为TService 的默认值,这个3个字段都是对应的IResolver <T>接口中的Current;在GetValueFromResolver方法中首先调用的是DependencyResolver.Current类中的GetService<TService>();构造函数中的callerMethodName是记录GetValueFromResolver方法出错的异常信息。

     DependencyResolver依赖解析器类

         DependencyResolver的作用在msdn上是这样注释的:“为实现 System.Web.Mvc.IDependencyResolver 或公共服务定位器 IServiceLocator 接口的依赖关系解析程序提供一个注册点。”;对于IDependencyResolver接口只有2个方法,主要密度是获取服务对象(object GetService(Type serviceType);)或是服务对象列表( IEnumerable<object> GetServices(Type serviceType);)。

         实现 IDependencyResolver接口的类有三个CacheDependencyResolver,DefaultDependencyResolver,DelegateBasedDependencyResolver类

        

     private class DefaultDependencyResolver : IDependencyResolver
     {
        public object GetService(Type serviceType)
        { 
    if (serviceType.IsInterface || serviceType.IsAbstract) { return null;} try{ return Activator.CreateInstance(serviceType); } catch { return null; } } public IEnumerable<object> GetServices(Type serviceType) { return Enumerable.Empty<object>(); }
    }

      在DefaultDependencyResolver类中的GetService方法中当参数serviceType为接口或抽象类时直接返回null,否则通过反射来创建对象;GetServices直接返回空的列表;

      private class DelegateBasedDependencyResolver : IDependencyResolver
      {
         private Func<Type, object> _getService;
         private Func<Type, IEnumerable<object>> _getServices;
         public DelegateBasedDependencyResolver(Func<Type, object> getService, Func<Type, IEnumerable<object>> getServices)
         {
            _getService = getService;
            _getServices = getServices;
         }
         public object GetService(Type type)
         {
           try
           {
             return _getService.Invoke(type);
           }
           catch
           {
             return null; 
    } } public IEnumerable<object> GetServices(Type type) { return _getServices(type); } }

        DelegateBasedDependencyResolver 类的构造函数接收2个委托方法参数,一个是返回值为object,参数为Type的类型的委托函数,一个是返回值为 IEnumerable<object>,参数为Type的类型的委托函数,在GetService或GetServices方法中执行委托函数的Invoke方法从而创造对象,这样做的函数是把对象的创建放在外部,提高程序的扩展性。

     

        private sealed class CacheDependencyResolver : IDependencyResolver
        {
           private readonly ConcurrentDictionary<Type, object> _cache = new ConcurrentDictionary<Type, object>();
           private readonly ConcurrentDictionary<Type, IEnumerable<object>> _cacheMultiple = new ConcurrentDictionary<Type, IEnumerable<object>>();
           private readonly Func<Type, object> _getServiceDelegate;
           private readonly Func<Type, IEnumerable<object>> _getServicesDelegate;
    private readonly IDependencyResolver _resolver;
           public CacheDependencyResolver(IDependencyResolver resolver)
           {
                _resolver = resolver;
                _getServiceDelegate = _resolver.GetService;
                _getServicesDelegate = _resolver.GetServices;
            }
            public object GetService(Type serviceType)
            {
               return _cache.GetOrAdd(serviceType, _getServiceDelegate);
            }
            public IEnumerable<object> GetServices(Type serviceType)
            {
               return _cacheMultiple.GetOrAdd(serviceType, _getServicesDelegate);
             }
        }

         对于CacheDependencyResolver 类就可以看出是做了一个缓存,当创建对象时,缓存里面有的话直接从缓存里面取值;

     关于DefaultDependencyResolver类与IDefaultDependencyResolver类时怎么关联呢?

        public class DependencyResolver
        {
            private static DependencyResolver _instance = new DependencyResolver();
    private IDependencyResolver _current; /// <summary> /// Cache should always be a new CacheDependencyResolver(_current). /// </summary> private CacheDependencyResolver _currentCache; public DependencyResolver() { InnerSetResolver(new DefaultDependencyResolver()); } public static IDependencyResolver Current { get { return _instance.InnerCurrent; } } internal static IDependencyResolver CurrentCache { get { return _instance.InnerCurrentCache; } } public IDependencyResolver InnerCurrent { get { return _current; } } /// <summary> /// Provides caching over results returned by Current. /// </summary> internal IDependencyResolver InnerCurrentCache { get { return _currentCache; } } }

      DefaultDependencyResolver类的属性Current就是返回IDefaultDependencyResolver接口对象,在DefaultDependencyResolver类的构造函数中默认用的DefaultDependencyResolver的类,InnerSetResolver方法主要是进行一些字段的赋值操作,而且还可以通过SetResolver方法来对_current,_currentCache字段进行赋值操作。

  • 相关阅读:
    11.菜单(一)
    线性表之顺序存储详解
    SVN 撤回已提交的代码
    线性表1
    顶层父类
    异常类之派生类
    new和delete重载
    异常类之基类
    Qt中多线程问题
    智能指针实例
  • 原文地址:https://www.cnblogs.com/h20064528/p/4997970.html
Copyright © 2020-2023  润新知