ASP.NET MVCのIresolver<br>インタフェース

8461 ワード

ASP.NET MVCのソースには、ControllerBuilder、ControllerFactory、Filters、ViewEnginesなどのエンティティオブジェクトがあります.キーワードnewで直接エンティティを作成するのではなく、Iresolverインタフェースに依頼します.また、Iresolverインタフェース自体も簡単で、フレームワークの拡張性も向上します.Iresolverは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(GetValueFromResolver)ではLazyクラスの新しいインスタンスが構築されています.パラメータはTServiceの戻り値を持つ委任GetValueFromResolverメソッドです.CurrentValueThunkもTServiceの戻り値を持つ委任方法です.defaultValueはTServiceのデフォルト値で、この3つのフィールドは対応するIresolverインタフェースのCurrentです.GetValueFromResolverメソッドで最初に呼び出されたのはDependencyResolverである.CurrentクラスのGetServices();コンストラクション関数のcallerMethodNameは、GetValue FromResolverメソッドのエラーを記録する例外情報です.
DependencyResolver依存解析クラス
DependencyResolverの役割はmsdn上でこのように注釈されている:“System.Web.Mvc.IDependencyResolverまたは公共サービスロケータIServiceLocatorインタフェースを実現する依存関係解析プログラムに登録ポイントを提供する.”IDependencyResolverインタフェースには2つの方法しかなく、主な密度はサービスオブジェクト(object GetService(Type serviceType);または、サービスオブジェクトのリスト(IEnumerableGetServices(Type serviceType);).
IDependencyResolverインタフェースを実装するクラスには、3つの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つの委任メソッドパラメータを受け取ります.1つは、戻り値がobject、パラメータがTypeのタイプの委任関数です.1つは、戻り値がIEnumerable、パラメータが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フィールドは、割り当て操作を行います.