ASP.NET CoreにおけるGetService()とGetRequiredService()の違い
7831 ワード
前回の記事『.NET Core 3.0のWPFでIOCグラフィックチュートリアルを使用する』では、WPFに
作者:依楽祝原文住所:https://www.cnblogs.com/yilezhu/p/11107648.html
ここでは、
サービスが存在しない場合、
ASP.NET Core依存注入抽象のコアは
DIコンテナ(
もちろん、通常は
しかし、時には選択の余地がないことがあります.たとえば、サービスを属性に注入しようとする場合や、DIコンテナの構成時に転送タイプを使用する場合は、
私たちがもう使わないことを考えると.NET 1.0では、
任意のコードを研究する前に,これらの方法の予想される挙動について議論しよう.まず、
したがって、要求されたインスタンス に戻る.
コードを見てみましょう
私はすでに本文のコードからいくつかの前提条件検査を削除しました.完全なコードを見たい場合は、GitHubで確認してください.
この2つの方法は実際には同じである−汎用拡張方法は非汎用バージョンの
非汎用バージョンの
この方法の第1のステップは、提供された
ASP.NET Coreに内蔵されているDI容器は
私が前に言ったように、理想的には、両方ともできます!
自分のコードで
GitHubで繰り返しを減らします.サービスが利用できない場合、 はすぐに失敗した. は、サードパーティ製コンテナの高度な診断を可能にする.StructureMapおよび他のサードパーティ製コンテナの大きな利点は、サービスが見つからない理由を説明する詳細な例外メッセージを提供することです.
もちろん、GetRequiredService()に反対するいくつかの観点を見ましたが、どちらも審査されないと思います.「サードパーティ製容器を使用していません」.内蔵コンテナを使用している場合( 「オプションのサービスがあり、DIコンテナにしか登録されていない場合があります.」これは
だから、今は
元の英語リンク:https://andrewlock.net/the-difference-between-getservice-and-getrquiredservice-in-asp-net-core/
.NET Core
内蔵のIOCを適用してプログラミングを試み、MainWindow
を解析する際にGetRequiredService()
の方法を使いました.その時、このGetRequiredService()
の方法とGetService()
の方法にはいったいどんな違いがあるのかと考えていました.そこで、グーグルは、彼らの違いを紹介する文章を見つけました.そこで、翻訳を試みました.皆さんに役に立つことを願っています.文章の最後に原文のリンクが表示されます.以下は翻訳内容です.作者:依楽祝原文住所:https://www.cnblogs.com/yilezhu/p/11107648.html
ここでは、
Microsoft.Extensions.DependencyInjection
で提供するデフォルト/内蔵ASPについて説明する.NET Core DI容器の方法GetService()
およびGetRequiredService()
.それらの違いと、どの方法を使用するべきかについて説明します.サービスが存在しない場合、
GetService()
はnull
GetRequiredService()
に戻り、異常を放出する.サードパーティ製コンテナを使用している場合は、可能な限りGetRequiredService
を使用します.例外が発生した場合、サードパーティ製コンテナは、異常情報に基づいて適切な診断情報を提供し、サービスが登録されていない理由を特定できます.コンテナのコア-IServiceProviderインタフェース
ASP.NET Core依存注入抽象のコアは
IServiceProvider
インタフェースである.このインタフェースは、実際にはSystem
ネーミングスペースのベースクラスライブラリの一部です.インタフェース自体は簡単です.public interface IServiceProvider
{
object GetService(Type serviceType);
}
DIコンテナ(
IServiceCollection
を使用)を使用してすべてのクラスを登録すると、ほとんどのDIコンテナがGetService()
を使用してオブジェクトのインスタンスを検索できるようにする必要があります.もちろん、通常は
IServiceProvider
をコードに直接使用するべきではありません.逆に、標準的なコンストラクション関数注入を使用して、フレームワークをベアリングさせ、バックグラウンドでIServiceProvider
を使用する必要があります.IServiceProvider
を直接使用することは、サービスロケータモードの一例である.これは通常、クラスの依存関係を隠すため、逆モードとみなされます.しかし、時には選択の余地がないことがあります.たとえば、サービスを属性に注入しようとする場合や、DIコンテナの構成時に転送タイプを使用する場合は、
IServiceProvider
を直接使用する必要があります.GetService()とGetRequiredService()の比較
私たちがもう使わないことを考えると.NET 1.0では、
IServiceProvider
からサービスを検索したい場合は、GetService()
インタフェースメソッドではなく、汎用的な汎用的なGetService(Type)
拡張メソッドを使用することができます.しかし、GetRequiredService()
のような拡張方法にも気づいたかもしれません.問題は、それらの間にどのような違いがあるのか、どの方法を使うべきかということです.任意のコードを研究する前に,これらの方法の予想される挙動について議論しよう.まず、
GetService()
メソッドのドキュメントから始めます.GetService()
は、serviceType
のタイプのサービスオブジェクトを返す.タイプのないサービスオブジェクトserviceType
が返された場合、null
が返される.GetRequiredService()
の文書の内容と比較します.GetRequiredService()
は、serviceType
のタイプのサービスオブジェクトを返す.serviceType
型のサービスがない場合、InvalidOperationException
異常が放出される.したがって、要求されたインスタンス
serviceType
が利用可能である場合、両方の方法の動作は同じである.異なる点は、serviceType
が登録されていない場合の動作です.GetService
-サービスが登録されていない場合、null
GetRequiredService
-サービスが登録されていない場合、Exception
例外が投げ出されます.コードを見てみましょう
ServiceProviderServiceExtensions
クラスでMicrosoftExtensions.DependencyInjection.Abstraactionsライブラリでは、以下に示すように、汎用版GetService()
とGetRequiredService()
の両方の方法が実装されています.私はすでに本文のコードからいくつかの前提条件検査を削除しました.完全なコードを見たい場合は、GitHubで確認してください.
public static class ServiceProviderServiceExtensions
{
public static T GetService(this IServiceProvider provider)
{
return (T)provider.GetService(typeof(T));
}
public static T GetRequiredService(this IServiceProvider provider)
{
return (T)provider.GetRequiredService(typeof(T));
}
}
この2つの方法は実際には同じである−汎用拡張方法は非汎用バージョンの
GetService()
およびGetRequiredService()
に委任される.これらはただの便利さなので、typeof()
とタイプ変換を自分のコードで使用する必要はありません.非汎用バージョンの
GetService()
はIServiceProvider
インタフェースの一部であるが、非汎用バージョンのGetRequiredService()
実装は同じクラスの拡張方法である.public static class ServiceProviderServiceExtensions
{
public static object GetRequiredService(this IServiceProvider provider, Type serviceType)
{
var requiredServiceSupportingProvider = provider as ISupportRequiredService;
if (requiredServiceSupportingProvider != null)
{
return requiredServiceSupportingProvider.GetRequiredService(serviceType);
}
var service = provider.GetService(serviceType);
if (service == null)
{
throw new InvalidOperationException(Resources.FormatNoServiceRegistered(serviceType));
}
return service;
}
}
この方法の第1のステップは、提供された
IServiceProvider
がISupportRequiredService
も実現したかどうかを確認することである.このインタフェースは、最下位の非汎用GetRequiredService
実装を提供するので、サービスプロバイダが実装する場合、GetRequiredService()
は直接呼び出すことができる.ASP.NET Coreに内蔵されているDI容器は
ISupportRequiredService
を実現していない-GetRequiredService()
を実現したのはサードパーティ容器のみである.IServiceProvider
がISupportRequiredService
を実装していない場合は、予想されるように、GetService()
呼び出し、null
を返すと例外が放出されます.どの方法を使うべきですか?
私が前に言ったように、理想的には、両方ともできます!
自分のコードで
ISeviceProvider
を使用するのは、通常、サービスロケータの逆モードを使用しているフラグなので、一般的にはISeviceProvider
を使用しないでください.ただし、設計上の制約が必要な場合(たとえば、属性でDIを使用できない場合)、またはDIコンテナ構成自体の一部として使用する場合、どちらを使用しますか?GitHubで
GetRequiredService()
を追加するように要求された元の問題と、Jeremy D.Millerが以前に提出した問題に基づいて、ほとんどの場合のルールは:GetRequiredService()
の使用GetRequiredService()
を使用すると、すぐに例外が放出されます.GetService()
を使用する場合は、呼び出しコードでnull
であるかどうかを確認し、通常は例外を放出する必要があります.その空のチェックコードはどこでも繰り返す必要があります.GetService()
を使用するときにnull
であるかどうかを確認するのを忘れた場合は、後でプログラムがNullReferenceException
で終了する可能性があります.異常の原因を特定するのは、明示的に教えてくれたInvalidOperationException
よりも困難で、より多くの仕事をする必要があります.GetRequiredService()
を使用している場合、サードパーティ製コンテナ自体に異常が発生するため、コンテナ固有の他の情報を提供できます.null
(GetService()
付き)だけを返すと、これ以上詳細な情報は表示されません.これがGetRequiredService()
の導入の主な原因である.もちろん、GetRequiredService()に反対するいくつかの観点を見ましたが、どちらも審査されないと思います.
ISupportRequiredService
は実装されていません)、他の診断を使用してGetRequiredService()
の利益を得ることはできません.しかし、前の2つの利点は依然として存在し、GetRequiredService
を使用する価値があると思います.また、後でサードパーティ製コンテナを追加する場合は、ベストプラクティスを使用しています.GetService()
を使用する唯一の有効な理由かもしれません.コードが特定のサービスに登録されている場合にのみ実行される場合は、GetService()
を使用する必要があります.しかし、GetService()
がNULLを返すと、私もそれがロールバックサービスを使用するときに使用されているのを見ました.私から見れば、これはアプリケーションコードの良いモードではありません.ロールバックの編成は、サービスを使用する場所ではなく、DIコンテナ構成の一部であるべきである.だから、今は
GetService()
とGetRequiredService()
の対比があります.さらに掘り起こす前に、もう一つではなく一つを選んだとき、私は少し武断しましたが、今はいつも当たり前のようにGetRequiredService()
を使っていることを確認します.サマリ
GetService()
はIServiceProvider
上の唯一の方法であり、ISeviceProvider
はASPである.NETコアDI抽象の中央インタフェース.サードパーティ製容器はまた、ISupportRequiredService
方法を提供するオプションのインターフェースGetRequiredService()
を実現することができる.要求のタイプserviceType
が利用可能である場合、これらの方法の動作は同じである.サービスが利用できない(すなわち登録されていない)場合、GetService()
はnull
を返し、GetRequiredService()
はInvalidOperationException
を投げ出す.GetRequiredService()
のGetService()
に対する主な利点は、サービスが利用できない場合、サードパーティ製コンテナに追加の診断情報を提供することを可能にすることである.従って、サードパーティ製容器を使用する場合にはGetRequiredService()
を使用することが望ましい.個人的には、内蔵のDI容器だけを使っても、どこでも使います.元の英語リンク:https://andrewlock.net/the-difference-between-getservice-and-getrquiredservice-in-asp-net-core/