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字段进行赋值操作。

原文地址:https://www.cnblogs.com/h20064528/p/4997970.html