2016-06-22 7 views
1

私はEFとAutofacでMVCを使用しています。ヘルパーと呼ばれる具体的なクラスがあります。 HelperはメインのMVC Webアプリケーションではなく、別のDLLにあります。Autofacプロパティ注入問題

DBContext型のプロパティに 'Context'というプロパティがあります。

DBContextのインスタンスをこのプロパティに挿入したいと思いますが、常にnullです。ここで

は私が世界でこれまで持っているものです。

var output = new DbContext(connectionString); 
    builder.RegisterInstance(output).As<DbContext>().PropertiesAutowired(); 
      builder.RegisterType<Helper().WithParameter("Context",output).PropertiesAutowired(); 

     // Set the dependency resolver to be Autofac. 
     var container = builder.Build(); 
     DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 

コンテキスト私はインスタンスの出力 "を注入したいヘルパークラスのプロパティです。

コンテキストは常にnullです。

+0

ヘルパークラスのコンストラクタ署名を渡せますか?私が知る限り、WithParameterまたはPropertiesAutowiredが必要ですが、両方ではありません。また、HelperコンストラクタにDbContext型のパラメータがある場合は、どちらも必要ありません。 –

+0

ご返信ありがとうございます。空のコンストラクタ、つまりpublic Helper(){}です。 – Chris

+0

'Context'プロパティのコードを共有できますか?それは一般に公開されていますか? –

答えて

8

Autofacでは、依存関係を管理する最も簡単な方法は、コンストラクタインジェクションを活用することです。

基本的には、Autofacに "私のためのプロパティを結び付けてあなたのモジョをする"と言っているのではなく、コンポーネントのリストを宣言することをあなたに任せてください。

ので

、代わりにプロパティの注入はヘルパーコンストラクタで明示的にあなたの依存関係を宣言し、動作していない理由を不思議の:

public class Helper 
{ 
    public DbContext Context { get; private set; } 

    public Helper(DbContext context /* Autofac is going to fill in this */) 
    { 
     Context = context; 
    } 
} 

次に、グローバルでの(またはご登録をカプセル化するいくつかの他のクラスで)あなただけにAutofacを伝えますHelperタイプを見て、あなたがすることができる最も簡単なことである最高のコンストラクタを呼び出すために彼の最善を試してみてください。

// Either InstancePerDependency, or SingleInstance, or something else depending upon you requirements. 
builder.RegisterType<Helper>().AsSelf().InstancePerDependency(); 

そして、あなたが行われる必要があります:Autofacは、ほとんどのパラメータ(およびTHERを持つコンストラクタを検索しますeはDbContextのパラメータを持つ唯一のものになり、要求されたタイプ(可能なもの)のパラメータを作成する方法を知っているかどうかをチェックします。

だから、あなたはすぐにヘルパーを使うことができます!

編集:私はそれは質問に対する正しい答えだから、上記の例を維持するんだけど、コメントに返信して、私はInitメソッドの形で、もう少し機械を使用します。

public class Helper 
{ 
    public DbContext Context { get; private set; } 

    public Init(DbContext context /* Autofac is going to fill in this */) 
    { 
     Context = context; 
    } 
} 

そして、あなたは、オブジェクトの初期化時に、このメソッドを呼び出すためにAutofacを指示することができます。

builder.RegisterType<CustomHelper>().AsSelf().InstancePerDependency() 
    .OnActivating(h => { 
     var dbContext = h.Context.Resolve<DbContext>(); 
     ((Helper)h.Instance).Init(context); 
    }); 

OnActivatingは、明示的な初期化呼び出しを記述することができます。 Helperから派生したアセンブリですべての型を登録したいと思うかもしれませんが、それはおそらく別の質問です。

+0

ご返信ありがとうございます。これは理想的な状況ですが、ヘルパーは基本クラスであり、Helperを継承するクラスでもそのコンストラクタにDbContextを持たせる必要はありません。オートファックがシステムにDbContextでオーバーロードされたコンストラクタを使用させる方法がありますか?再度、感謝します。 – Chris

+0

あなたの答えをありがとう。これは良い仕事です。しかし、私はInitメソッドにブレークポイントを張りつけ、決して呼び出されません。ここに私のグローバルです:var output = new DbContext(connectionString); builder.RegisterType ().AsSelf()InstancePerDependency() .OnActivating(H => { ((BaseHelper)h.Instance).INIT(出力); })。 – Chris

+0

継承は非常にDIフレンドリではありません。より良いアプローチは、デコレータやプロキシなどのよりDIに優しいパターンを使用するようにデザインを変更する(可能な場合)ため、具体的なインスタンスで 'DbContext'の依存関係を直接要求しないようにすることです。インスピレーションのために[フィルタ](http://stackoverflow.com/a/28365933/181087)がMVCで動作する方法を見てください。 – NightOwl888

関連する問題