私はDIとその使い方に関する多くのドキュメントを読んだことがあります(ASP.NETコアに関連しています)。私が理解しているように、フレームワークが私のためにいくつかのコントローラをインスタンス化するとき、コントローラのクラスがコンストラクタに渡す必要があることを何とか知っています。それは反射か何か?誰かが私にASP.NET Core GitHubのソースでそれを見ることができる場所を教えてもらえますか?コンテナに必要なもの(DIALコンテナ)はDIコンテナでどのように認識されていますか?
2
A
答えて
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)));
}
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
ありがとう、私が探していたもの –
関連する問題
- 1. 添付された子どもがコンテナによって認識されない
- 2. DIコンテナは工場にどのようなメリットをもたらしますか?
- 3. DIコンテナのサービスロケータ
- 4. DIコンテナはこの
- 5. Symfony DIコンテナのコンフィグレーションプロンプト
- 6. IoC/DIコンテナが「コンテナ」と呼ばれるのはなぜですか?
- 7. DDDのドメインインフラストラクチャサービス用にDIコンテナを設定する必要はありますか?
- 8. クラウドのコンテナにはどのようなものが適していますか?
- 9. C++のリストがコンテナとして認識されませんか?
- 10. なぜLaravelにDIコンテナがないのですか?
- 11. RESTクライアントのPHP - DIコンテナ
- 12. Windows MobileアプリケーションのIoC/DIコンテナ
- 13. コンテナ名がコンテナによって既に使用されています - gitlab ci
- 14. オーラDIコンテナを作成するには?
- 15. Dockerコンテナでシリアルポートデバイスが認識されない
- 16. リンクされたphp DockerコンテナからDockerコンテナ内のnginx vhostにどのように接続できますか?
- 17. は、私はこのような移動コンテナに移動し、コンテナ
- 18. Dockerコンテナの非ボリュームデータはどのように格納されていますか?
- 19. 理論: "サービスロケータ" "IOCコンテナ" "IOC" "DI"
- 20. 親コンテナをホバリングされた子コンテナの高さにします
- 21. 単体テストでのDIコンテナの使用
- 22. ビットマップにはどのようなコンテナを使用しますか?
- 23. コンテナにはどのようなタイプがありますか?
- 24. Docker:コンテナ内のボリュームを持たないコンテナはどのようにデータを保持しますか?
- 25. コンテナがC++に必要です
- 26. Nservicebusはどのようにstructuremapのネストされたコンテナを扱いますか?
- 27. 子コンテナ内のイメージスライダを親コンテナの幅よりも幅広にするには?
- 28. jenkinsコンテナ(jenkins)のユーザをコンテナ内のグループ(ユーザ)に追加するにはどうすればいいですか?
- 29. 1つのコンテナを別のコンテナに移動するにはどうすればいいですか?
- 30. Symfony DIコンテナ自体をサービスに挿入するにはどうすればよいですか?
複数のコンストラクタを持つタイプをサポートしています。 – Nkosi
@Nkosi:現在のrc1は、複数のコンストラクタを持つ型を受け入れません。 – Steven
間違ったコードを見ていますか?私が読んでいるコードを誤解している可能性があります。 https://github.com/aspnet/DependencyInjection/blob/4f2e6f035662b73936a2ed4fc249c163c9978c91/src/Microsoft.Extensions.DependencyInjection/ServiceLookup/Service.cs – Nkosi