[ASP.NETコア3フレーム開示]依存性注入:依存性注入モード

IOCは、主にこのような設計思想:コントロールの一般的な流れのグループによって多重化処理を実現するためにフレームにアプリケーションから転送され、そして達成するために、「ハリウッドの規則」の適用に応じて、フレームとコードの間であります相互作用。私たちは、このような私たちのテンプレート以前に記載された方法、方法および抽象工場の工場として仕方のIoC、異なるデザインパターンの番号を使用することができ、その後、我々はより価値のIoCパターンを紹介:依存性の注入(DI:依存性注入)。

まず、オブジェクトは、コンテナが提供します

方法及び植物前述したと同じ抽象工場モデル、依存性注入は、オブジェクトが我々は総称して「サービス」、「クライアント」として、または呼ばれるデザインパターン「オブジェクト提供」「サービスインスタンス」を 依存性の注入を使用するアプリケーションでは、我々はタイプを定義し、あなたはそれの上で来る注入対応する方法を使用してサービスに直接に依存することができます。

アプリケーションが起動すると、私たちは、グローバルレジスタにサービスを提供する必要があります。一般的に、サービスは、ほとんどのインターフェイスのために登録したり、抽象クラスを継承し、我々は消費の後工程でサービスインスタンスに対応する登録情報を提供するサービスを支援します。「ハリウッドのルール」によると、唯一のサービスインスタンスを提供し、必要な優れたサービスを定義し、登録する必要があるアプリケーションをフレームワークに完全に達成され、フレームワークは、すべての必要を提供するために、別個の「容器(コンテナ)」を使用しますサービスインスタンス。

私たちのフレームワークは、以前のIoCのために説明によると、「IoCコンテナ」と呼ばれる人が多い「依存性注入コンテナ」と呼ばれるこのサービスコンテナを提供するために使用されますが、私は後者のが合理的なタイトルだとは思いません。依存性注入コンテナが含まれるサービスインスタンスを提供するために必要なすべての情報、サービス登録、我々は彼らが、コンテナは、登録情報に基づいてサービスを作成することですので、必要なサービスを提供したい道をたどることができました。

<T>のgetServiceを次の猫オブジェクトからサービスオブジェクトの指定された型を取得して簡単な例として、我々は依存性注入コンテナ猫という名前の型を作成し、我々は、この拡張メソッドを呼び出すことができます。私たちのすべてから、私は猫と名付けた理由は、漫画に非常に精通している「ドラえもん(ドリーム)。」依存性注入コンテナに最適ですバイキングの4次元ポケット、クマはちょうどそれが対応する魔法を与えるために、このポケットからで、夢を対応するデュオの需要を伝える必要があります。依存性注入はまた、真コンテナであり、消費者は、容器必要なサービス(典型的にはサービスインタフェースまたは抽象サービスクラス)のサービスタイプを指示するサービスインスタンスに一致を得ることができる必要があります。

パブリック 静的 クラスCatExtensions 
{   
    パブリック 静的 TのgetService <T>(この猫ネコ); 
}

私たちのプレゼンテーションのためのMVCフレームワーク、我々はコアタイプのフレームの前に異なるデザインパターンを使用していたがMvcEngine「形質転換」だったと今、私たちは、注射依存的に使用し、コンテナの猫を使用すると、このように次のそれを再実装、我々はMvcEngineは非常にシンプルで明確になるでしょう。

パブリック クラスMvcEngine 
{ 
    公共猫猫{ 取得します}
     公共 MvcEngine(猫の猫)=>猫= 猫。
        
    パブリック 非同期タスクStartAsync(URIアドレス)
    { 
        VARのリスナー= Cat.GetService <IWebListener> ();
        VaRの活性化因子= Cat.GetService <IControllerActivator> ();
        VaRのキュータ= Cat.GetService <IControllerExecutor> ();
        VaRのレンダラ= Cat.GetService <IViewRenderer> (); 

        待つlistener.ListenAsync(アドレス)。
        しばらく 
        {
            VARのHttpContext = 待つlistener.ReceiveAsync()を。
            VaRのコントローラ= 待つactivator.CreateControllerAsyncを(のHttpContext)。
            試す
            { 
                VARのビュー=を待つ(コントローラのHttpContext)executor.ExecuteAsyncと、
                待つrenderer.RenderAsync(ビュー、のHttpContext)。
            } 
            最後に
            { 
                待つactivator.ReleaseAsync(コントローラ)。
            } 
        } 
    }         
}

依存性の注入は、最も直接的なサービスの消費パターンのいずれかを体現、消費者は唯一のプロバイダ(依存性注入コンテナ)を指示する必要があり、サービスのインスタンスを提供することができ、必要なサービスの種類は、ルールに従ってあらかじめ登録一致します。登録サービスの依存性注入コンテナの最終決定は、サービスの指定されたタイプに応じて、サービスインスタンスの種類を提供しますので、我々はサービスがフレームをカスタマイズ登録された方法を変更することにより行うことができますので。アプリケーションは、単一の先に定義されたSingletonControllerActivatorの実施の形態では活性化されたターゲット・コントローラーを使用する必要がある場合、それは注射を開始すると、コンテナに依存するであろう前に、登録SingletonControllerActivator次のフォームMvcEngineであろう。

パブリック クラスのApp 
{ 
    静的な 無効メイン(文字列[] argsを)
    { 
        VARの猫= 新しいキャット().Register <ControllerActivator、SingletonControllerActivator> ();
        VaRのエンジン= 新しいMvcEngine(猫)。
        VaRのアドレス= 新しいウリ(" のhttp:// localhost /をmvcapp " ); 
        engine.StartAsync(アドレス); 
    } 
}

2つ、3つ、依存性注入

タスクは、多くの場合、複数のオブジェクトを完了するために協力、またはオブジェクトがいくつか必要な手順を完了するためのタスクを完了するための時間に、直接的または間接的に他のオブジェクトに依存する必要があることを要求するので、オブジェクト間の実行時の依存関係関係は、対象タスクによって決定された引数を「デカップリング」がない、自然に、「定数」です。ランタイムオブジェクトは、クラス間の結合が低減または終了する依存的に抽象化することにより、対応するクラスによって定義されます。

ビューのサービスの消費者の観点から、抽象サービスへのインターフェースによって消費をWE、サービスの特定の種類のサービスコンシューマプログラムは、サービス・インターフェースに依存するために、上記転送することができますに依存しますが、実行時に消費者に常に利用可能これは、サービスの特定のタイプのターゲットです。また、サービス・インターフェースでカスタムアクションを実行するには、このオブジェクトは、他の言葉で、オブジェクトが提供する依存サービスが他のサービスオブジェクトに依存していることが、他の関連オブジェクトに参加する必要があるかもしれません。容器内にターゲット依存サービスプロバイダとしては、依存関係チェーンの本実施例に係るすべての依存サービスを提供します。

以下に示すように、アプリケーション・フレームワークは、従属IFooサービスオブジェクトを取得するために血管内に注入のgetService <IFoo>メソッドを呼び出し、予め登録されたオブジェクトベースのFooマッピング関係のタイプを作成するインタフェースを実装します。Fooのオブジェクトが操作対象を完了するために、バーやGUXオブジェクトに参加する必要があるので、それはFooのバーとのGUXのための直接的な依存関係を持っています。クライアントとしてバーは、それはバズを依存している、そしてバズはフーの間接的依存になりました。提供される最後の注射のFooオブジェクトコンテナに依存し、それは直接的または間接的に従属オブジェクトバー、バズとQuxが以前に初期化され、自動的に被検体に注入されます。

3-5

オブジェクト指向プログラミングの観点からフィールドまたは属性タイプがフォームに主に依存しているに、懸念されます。タイプA、タイプBのフィールドまたは属性を持っている場合、AはBに依存して生成され、我々は単に依存フィールドまたは属性のための自動化された方法を初期化する依存性注入として理解することができます。私たちは、主に次の3通りの方法でこれを達成することができ、これは、依存性注入、以下の3種類のハイライトです。

コンストラクタ・インジェクション

コンストラクタは、それによって作成されたオブジェクトへの注射によって、コンストラクタパラメータの従属オブジェクトに注入されます。読み取り専用プロパティではFooバー依存性のために以下のコード断片は、属性、コンストラクタによって提供されるパラメータを渡す特定の属性値の初期化コンストラクタに実装、バーに反映されています。

パブリック クラスはFoo 
{ 
    公共 IBARバー{ 得る;}
     公共のFoo(IBARバー)=>バー= バール。
}

加えて、注射装置の構成は、さらにコンストラクタの選択に反映します。次のコードは、FooのクラスはFooのオブジェクトを作成する前に、適切なコンフィギュレーション機能を選択するための2つのコンストラクタ依存性注入コンテナ最初の必要性を定義します。ターゲット・コンストラクタを選択する方法としては、異なる依存性注入コンテナは、異なるポリシーを有していてもよく、そのようなパラメータが選択されてもよいし、少なくともアップコンストラクタに、以下に示すようにして目標特性InjectionAttributeコンストラクタ上にマークされてもよいです。

パブリック クラスはFoo 
{ 
    公共 IBARバー{ 得る;}
     公共 IBazバズ{ 得る;} 

    [インジェクション] 
    公共のFoo(IBARバー)=>バー= バール。
    公共のFoo(IBARバー、IBaz):この(バー)=>バズ= バズ。
}

プロパティインジェクション

あなたが直接、属性のクラスを反映し、読み取り専用属性ではない依存している場合、我々は、オブジェクトが作成された後、依存性注入の目的を達成するように自動的に割り当てることが依存性注入コンテナを作ることができます。私たちはこのタイプを定義する際に一般的に、自動的に他の一般的な性質と区別するために、依存関係の属性を噴射する明示的な属性として識別することが必要です。次のコードは、Fooのクラスは、2つのパブリックプロパティを書き込み可能なバーやバズを定義して、我々は自動的にバズ依存関係プロパティを注入されたように設定InjectionAttribute特性属性をタグ付けする方法で持っています。依存性注入によって提供Fooのオブジェクトコンテナのため、バズその特性が自動的に初期化されます。

パブリック クラスFooの
{ 
    公共 IBARバー{ 取得しますセット;} 

    [インジェクション] 
    パブリック IBazバズ{ 得ますセット;} 
}

メソッド・インジェクション

反射し、フィールドまたは属性の依存関係は、初期化の方法の形態とすることができます。フーバーのための次のコード、メソッドに渡されたパラメータによって提供される特定の属性値を属性を初期化する初期化方法で実装読み取り専用属性に反映依存。我々はまた、インジェクション法として同定される方法の特徴的な方法(InjectionAttribute)でマーク。Fooのオブジェクトのコンストラクタを作成した後依存性注入コンテナが呼び出されると、自動的に読み取り専用プロパティバーを割り当てるために、Initializeメソッドを呼び出します。

パブリック クラスはFoo 
{ 
    公共 IBARバー{ 得る;} 

    [インジェクション] 
    パブリック初期化(IBARバー)=>バー= バール。
}

上記自動初期化コールサービスプロセスに依存し、それを通して容器に注入達成に加えて、我々はまた、それを自由注入を達成するために別の方法を使用することができ、この注入方法は、ASP.NETコアアプリケーションに広い用途を有します。それはインタフェースを実装する必要がない場合ASP.NETコアは登録ミドルウェアを完了するために、登録されたスタートアップオブジェクトを呼び出します起動時に、私たちはスタートアップの種類を定義し、設定用ミドルウェアの登録方法は、固定されていません文は、我々はサービスの任意のインスタンスに依存して、以下の方法が直接このメソッドに注入されて従うことができます。

パブリック クラススタートアップ
{ 
    公共の 無効設定(IApplicationBuilderアプリ、IFoo fooという、IBARバー、IBazバズ)。
}

同様の注入方法は、ミドルウェアの定義と同じタイプに適用されます。ミドルウェアを登録するために、スタートアップの種類と同様に、ASP.NETコアフレームワークにおけるミドルウェアタイプもリクエストを処理するための事前定義されたインタフェース、またはInvokeAsync Invokeメソッドを実装する必要があり、以下のように、任意の方法で注入することができます依存サービス。

パブリック クラスFoobarMiddleware 
{ 
    プライベート 読み取り専用RequestDelegateの_next。 
    公共 FoobarMiddleware(RequestDelegate次)=> _next = 次回。

    パブリックタスクInvokeAsync(のHttpContextのHttpContext、IFoo FOO、IBARバー、IBazバズ)。
}

このように、上記の方法は、「大会指向」プログラミングの注入につながりました。事前定義されたインタフェースを実現または特定の事前定義された基本クラスステートメントのオーバーライドを継承またはメソッドを実装する必要がありする必要性を排除することによって最も直接的な可能な方法に依存するサービス噴射するように、制限の少ない対応であろう方法へ。前述の注入方法のこれらのタイプでは、コンストラクタ・インジェクションが最も理想的な形で、私は個人的に射出注入(前述の方法は、上で同意したことを除いて、注射)のプロパティとメソッドを使用することをお勧めしません。

三、サービスロケータパターン

我々は、サービスFoo型を定義する必要があると、それは二つの追加サービスのバーとバズに依存して、サービスとインタフェースに対応し、後者はIBAR IBazです。依存性を有する電流印加噴射容器(我々は上記で定義された同様の猫を想定)した場合、我々は、サービスタイプはFooを定義するには、次の2つの方法を使用することができます。

パブリック クラスFooの:IFoo 
{ 
    公共 IBARバー{ 取得します}
     公共 IBazバズ{ 得ます}
     公共のFoo(IBARバー、IBazバズ)
    { 
        バー = バール。
        バズ = バズ。
    }   
    パブリック 非同期タスクInvokeAsync()
    { 
        待つBar.InvokeAsyncを();
        待つBaz.InvokeAsyncを(); 
    } 
} 

パブリック クラスFooの:IFoo 
{ 
    公共猫猫{ 取得します}
     パブリックフー(猫猫)=>猫= 猫。 
    パブリック 非同期タスクInvokeAsync()
    { 
        待つ Cat.GetService <IBAR> ().InvokeAsync();
        待つ Cat.GetService <IBaz> ().InvokeAsync(); 
    } 
}

表面には、サービスのこれらの2つのタイプが定義された上記の方法がよさそうだ、少なくとも彼らは、カップリングの問題のために依存するすべてのサービス・ソリューションであり、インタフェースのために頼るようにサービスの実装のための移行に依存します。だから、これは良いですか?私はこれが唯一のサービスを提供し、より直接的なため、道少ないコードで定義されていないため、一部の人は、道の2番目の定義を選択すると思います。私たちは、直接「依存性注入コンテナ、」猫のオブジェクトの代表と「注入された」コンストラクタで、どこかのサービスに依存するように、我々はそれを提供するために、対応するサービスインスタンスを使用する必要があります。

しかし、実際にはデザインパターンを使用2番目の定義方法は、単純である、「依存性注入」ではないが、「と呼ばれるサービスロケータ」デザインパターン。サービスロケータパターンもコンテナは、「サービスロケータ」と呼ばれ、必要なサービスインスタンスを提供するために、グローバルなコンテナサービスによって作成されたレジストリを持っています。「依存性注入コンテナ」と「サービスロケータは、」実際に塗りつぶしの異なるデザインパターンで同じもの異なった名前は、その後、依存性注入とサービスロケータの違いはどのような場所に反映されていますか?

私は2つの違いは角度や「サービスロケータ」から利用「のコンテナ依存への」著名なデザインパターンことができると思います。依存性注入の使用のアプリケーションでは、我々は唯一のアプリケーションがそれを開始する前に、動作中にそのエンジンのフレームワークは依存性注入コンテナを使用する優れたサービスタイプの定義の標準的な射出フォームを必要とし、サービス登録を完了します現在必要なサービスインスタンスを提供します。換言すれば、依存性ではなく、ユーザアプリケーションのコンテナ枠に注入しなければなりません明確サービスロケータパターンではない場合、そのように、アプリケーションは、必要なサービスインスタンスを提供するために、それを使用することは明らかであるユーザーがアプリケーションです

我々はまた別の角度から、それらの間の違いを見分けることができます。依存サービスを提供するように「注入」されるので、アプリケーションの依存性注入パターンの使用は、サービスとして見ることができるので、「プッシュアプリケーションモードでは、依存性注入容器に」「するサービスロケータサービスロケータを使用することであるプル」必要なサービスを取る、プッシュプルを正確に両者の違いを反映することができます。両者の間に差があるので、まあ、それは本当に良いですか?

戻る2010年に、彼の中にマーク・シーマンブログ何人かの人々が異なる意見を持っているが、サービスロケータは、「抗モード(アンチパターン)」とみなされますが、私は個人的に非常にこれを使用することはお勧めしません。デザインパターン。私は注射は同様の理由を持って注入サービスロケータを使用して反対し、前述のプロパティとメソッドの使用反対です。

「疎結合、非常に凝集」設計原理の精神、我々はサービスと多重化に関連する一連のアクションを定義することから、それはサービス自体を主張しようとする必要があり自立と自律性の特性を持っていますが、またサービスの要件だけでなく、間には、明確な境界を持っている必要があり、サービス間の依存関係が明確で曖昧ではないはずです。プロパティの注射または注入法を使用して、または間違いなく現在のサービスがされ、現在の依存サービス、提供するサービスロケータを使用しているかどうか、新たな依存関係を追加している容器や依存のためのサービスロケータ依存性に注入され、。

現在のサービスは、依存性注入容器又はサービスロケータの依存性やその他のサービスのために、それは「に基づいて、サービスベースのインタフェースまたは実装タイプであるかどうかを、前者は依存性のタイプであり、本質的に異なる依存した契約」依存性。この依存性だけではない明確でなく、保証の。しかし、依存性注入コンテナまたはサービスロケータは、本質的にブラックボックス、それは必要なサービスを提供することができますが提供されている対応するサービスは、事前にコンテナに追加登録されているが、この依存性はないが曖昧でなく、信頼性の低いインチ

依存性注入フレームワークASP.NETコアフレームワークにのみ使用してコンストラクタ・インジェクションをサポートし、(合意に基づく場合を除き起動に類似しており、ミドルウェア・インジェクション)プロパティとメソッドインジェクションをサポートしていませんが、我々は、おそらく無意識のうちにサービス従います私たちのコードを記述するロケータパターン。我々はサービスインスタンスを抽出するためのプログラムIServiceProvider(代表依存性注入コンテナ)で使用するとき意味では、それは我々がすでにサービスロケータパターンを使用していることを意味し、私たちはこのような状況が発生したときとき一部がそうする必要があるかどうかを熟考する必要があります。

[ASP.NETコア3フレーム開示]依存性注入:制御の反転
[ASP.NETコア3フレーム開示]依存性注入:IoCのモード
[ASP.NETコア3フレーム開示]依存性注入:依存性注入モード
[ASP.NETコア3フレームワークシークレット]の依存性注入:DIフレームワークのミニバージョン

おすすめ

転載: www.cnblogs.com/artech/p/inside-asp-net-core-03-03.html