2017-05-16 11 views
0

私は依存性注入について学んでいるので、私も理解しました(あなたがそうする気持ちがあればどこでも修正してください)。次のサンプルのコンセプトは、依存関係注入を使用する利点を確認することです。具体的な定義(クラス)の傾向がある場合に、将来変わる。ASP.NETコアアプリケーションでDependency Injectionを実装中にInvalidOperationExceptionが発生しました

IEmailService - インタフェース:

public interface IEmailService 
{ 
    void SendMail(); 
} 

EmailService - クラス

public class EmailService : IEmailService 
{ 
    public EmailService(string emailFrom, string emailTo) 
    { 

    } 

    public void SendMail() 
    { 
     // Code here 
    } 
} 

インターフェース上に継承にHomeController

public class HomeController : Controller 
{ 
    private IEmailService _service; 

    public HomeController(IEmailService service) 
    { 
     _service = service; 
    } 

    public IActionResult Index() 
    { 
     _service.SendMail(); 
     return View(); 
    } 
} 

Startup.cs

public void ConfigureServices(IServiceCollection services) 
{ 
    // Add framework services. 
    ... 
    services.AddTransient<IEmailService, EmailService>(); 
    ... 
} 

実践的な仮定

は、私が以前EmailServiceクラスには、パラメータ化コンストラクタがなかったと仮定し、私は追加する必要があるように、将来的に、私は感じて(HomeControllerのような)抽象化(インタフェース)を使用してthにアクセスするコントローラに影響を与えるべきではありません間接的に。

残念ながら、上記のコードを実行しているときに、パラメータ化されたコンストラクタをEmailServiceクラスから削除すると消えるような次の例外が発生しています。

InvalidOperationException: 'DependencyInjectionDemo.Services.EmailService'をアクティブ化しようとしているときに、 'System.String'タイプのサービスを解決できません。

+0

これは、より多くのように見えるので、私は、 'のSendMail()'メソッドに '文字列emailFrom、文字列emailTo'を移動しますメソッドの責任。その後、DIは再び動作します。また、DIフレームワークが注入するすべてのものは 'ConfigureServices'に登録する必要があります。 – Ignas

+0

良い点@Ignas :)コンストラクタ内で初期化する必要があるEmailServiceクラスに定義されているグローバル変数があるとします。ちなみに、このコードは学習目的にすぎません。だから私は回避策を見つけるのではなく、そのような問題に遭遇する正しい方法を見つけようとしています。 –

+0

"私は依存性注入について学んでいる"。 Proのヒント:依存性注入に関する本の[この紹介の章](https://manning-content.s3.amazonaws.com/download/7/f7d17b7-f62d-4dcd-9bc7-8a261e6aa4a8/Seemann2_DEidotNET2E_MEAP_V01_ch1.pdf)を読んでください。 – Steven

答えて

4

あなたは、ラムダを使用してEmailService登録することができます。

services.AddTransient<IEmailService>(_ => new EmailService("[email protected]", "[email protected]")); 

emailFromemailToしかしコントローラがIEmailServiceにこの情報を提供する責任があるかもしれないことを意味し、ランタイムデータに見えます。 EmailServiceはコントローラーからのデカップリングされているため、コントローラーがその作成を担当していないことを意味します。一般的に

、あなたはhereが説明したように、実行時のデータを使用してコンポーネント(あなたのケースでEmailService)を初期化する必要が防ぐ必要があり、アドバイスは次のとおりです。

時にアプリケーションコンポーネントにランタイムデータを注入しないでください。建設;あいまいさを引き起こし、余分な責任で構成ルートを複雑にし、DI構成の正確性を確認することが非常に困難になります。私のアドバイスは、実行時データが、構築されたオブジェクトグラフのメソッド呼び出しを流れるようにすることです。あなたのケースでは

これは、基本的には次のIEmailService抽象化を変更することを意味:

public interface IEmailService 
{ 
    void SendMail(string emailFrom, string emailTo); 
} 
+0

あなたのコメントをありがとう:)。一方、私はあなたが私に何を提案したかを得ています。 ASP.NET CoreのDIを使用して、インタフェースが最小限のコード保守性(上記のサンプルコードで達成しようとしていたもの)で役立つ実用的なサンプルにリダイレクトできますか? –

+0

@AjendraPrasad:あなたがここで何を求めているのか分かりません。あなた自身の質問は、インターフェイスが役立つところの実際的な最小例です。 IEmailServiceは実用的な例です。 – Steven

+0

ご迷惑をおかけして申し訳ありません。私が言いたいのは、HomeControllerにIEmailServiceを注入しているときに、EmailServiceの実際の実装が(少なくともパラメータ化されたコンストラクタを追加しないと)変化する可能性があるということです。したがって、具体的なクラス定義の変更により、コードを変更する必要はありません。あなたがそれを持っていればと思います:) –

関連する問題