2016-04-11 22 views
2

私はDIとその使い方に関する多くのドキュメントを読んだことがあります(ASP.NETコアに関連しています)。私が理解しているように、フレームワークが私のためにいくつかのコントローラをインスタンス化するとき、コントローラのクラスがコンストラクタに渡す必要があることを何とか知っています。それは反射か何か?誰かが私にASP.NET Core GitHubのソースでそれを見ることができる場所を教えてもらえますか?コンテナに必要なもの(DIALコンテナ)はDIコンテナでどのように認識されていますか?

答えて

2

現在のRC1上のASP.NET Core DIのコンストラクタ選択動作は、かなり複雑です。これまでは、単一のコンストラクタを持つ型だけをサポートしていました。これはvery good defaultです。しかしRC1では、複数のコンストラクタを持つ型を受け入れます。それでも、その動作は非常に奇妙で、テスト中にDIコンテナに複数のコンストラクタを持つ私のコンポーネントを作成させることはできませんでした。

コンストラクタの選択とコンストラクタパラメータの分析はすべてリフレクションを使用して行われ、式ツリーが構築され、最終的にデリゲートにコンパイルされます。コードはthisと同じくらい簡単です:

public Expression Build(Expression provider) 
{ 
    var parameters = _constructorInfo.GetParameters(); 
    return Expression.New(
     _constructorInfo, 
     _parameterCallSites.Select((callSite, index) => 
      Expression.Convert(
       callSite.Build(provider), 
       parameters[index].ParameterType))); 
} 
+0

複数のコンストラクタを持つタイプをサポートしています。 – Nkosi

+0

@Nkosi:現在のrc1は、複数のコンストラクタを持つ型を受け入れません。 – Steven

+0

間違ったコードを見ていますか?私が読んでいるコードを誤解している可能性があります。 https://github.com/aspnet/DependencyInjection/blob/4f2e6f035662b73936a2ed4fc249c163c9978c91/src/Microsoft.Extensions.DependencyInjection/ServiceLookup/Service.cs – Nkosi

7

あなたはGitHubの上hereを探し始めることができます。

ナットシェルでは、リフレクションを使用して、タイプのパブリックコンストラクタとそのパラメータを検査しています。

var constructors = _descriptor.ImplementationType.GetTypeInfo() 
     .DeclaredConstructors 
     .Where(constructor => constructor.IsPublic) 
     .ToArray(); 

パラメータの長さに基づいてコンストラクタをソートし、最適なものを選択します。

このスニペットは、インスタンス化される型を呼び出すための最適なコンストラクタを探します。

public IServiceCallSite CreateCallSite(ServiceProvider provider, ISet<Type> callSiteChain) 
{ 
    var constructors = _descriptor.ImplementationType.GetTypeInfo() 
     .DeclaredConstructors 
     .Where(constructor => constructor.IsPublic) 
     .ToArray(); 

    IServiceCallSite[] parameterCallSites = null; 

    if (constructors.Length == 0) 
    { 
     throw new InvalidOperationException(Resources.FormatNoConstructorMatch(_descriptor.ImplementationType)); 
    } 
    else if (constructors.Length == 1) 
    { 
     var constructor = constructors[0]; 
     var parameters = constructor.GetParameters(); 
     if (parameters.Length == 0) 
     { 
      return new CreateInstanceCallSite(_descriptor); 
     } 

     parameterCallSites = PopulateCallSites(
      provider, 
      callSiteChain, 
      parameters, 
      throwIfCallSiteNotFound: true); 

     return new ConstructorCallSite(constructor, parameterCallSites); 
    } 

    Array.Sort(constructors, 
     (a, b) => b.GetParameters().Length.CompareTo(a.GetParameters().Length)); 

    ConstructorInfo bestConstructor = null; 
    HashSet<Type> bestConstructorParameterTypes = null; 
    for (var i = 0; i < constructors.Length; i++) 
    { 
     var parameters = constructors[i].GetParameters(); 

     var currentParameterCallSites = PopulateCallSites(
      provider, 
      callSiteChain, 
      parameters, 
      throwIfCallSiteNotFound: false); 

     if (currentParameterCallSites != null) 
     { 
      if (bestConstructor == null) 
      { 
       bestConstructor = constructors[i]; 
       parameterCallSites = currentParameterCallSites; 
      } 
      else 
      { 
       // Since we're visiting constructors in decreasing order of number of parameters, 
       // we'll only see ambiguities or supersets once we've seen a 'bestConstructor'. 

       if (bestConstructorParameterTypes == null) 
       { 
        bestConstructorParameterTypes = new HashSet<Type>(
         bestConstructor.GetParameters().Select(p => p.ParameterType)); 
       } 

       if (!bestConstructorParameterTypes.IsSupersetOf(parameters.Select(p => p.ParameterType))) 
       { 
        // Ambigious match exception 
        var message = string.Join(
         Environment.NewLine, 
         Resources.FormatAmbigiousConstructorException(_descriptor.ImplementationType), 
         bestConstructor, 
         constructors[i]); 
        throw new InvalidOperationException(message); 
       } 
      } 
     } 
    } 

    if (bestConstructor == null) 
    { 
     throw new InvalidOperationException(
      Resources.FormatUnableToActivateTypeException(_descriptor.ImplementationType)); 
    } 
    else 
    { 
     Debug.Assert(parameterCallSites != null); 
     return parameterCallSites.Length == 0 ? 
      (IServiceCallSite)new CreateInstanceCallSite(_descriptor) : 
      new ConstructorCallSite(bestConstructor, parameterCallSites); 
    } 
} 
+1

ありがとう、私が探していたもの –

関連する問題