2017-05-18 15 views
0

私はC#Asp.Netアプリケーションを構築しています。 私のプロジェクトには3つのアセンブリがあります。Autofac Dependency Injection - アセンブリに基づいて異なるタイプに解決する

  • MainAssembly
  • AssemblyA
  • AssemblyB

AssemblyAAssemblyBはMainAssemblyへの参照を有します。 MainAssemblyはReflectionを使用してAssemblyAAssemblyBをロードします。 タイプが存在するアセンブリに基づいてタイプを解決する必要があります。

つまり、コンストラクタパラメータは、それが属するアセンブリに基づいて、SmsSenderまたはEmailSenderに解決される必要があります。

はコードの下に考えてみましょう:

-------------------------- コードMainAssembly内部------- -------------------

//Global Registration 
void AutofacRegister() 
{ 
    var builder = new ContainerBuilder(); 
    ... 
    ... 
    //Registering the modules in other assemblies 
    builder.RegisterAssemblyModules(AssemblyA); 
    builder.RegisterAssemblyModules(AssemblyB); 
    ... 

} 

interface ISender 
{ 
    void SendMessage(); 
} 

------------------------ - AssemblyB内部コード----------------------------

public class ComponentA: Module 
{ 
    protected override void Load(ContainerBuilder builder) 
    { 
     builder.RegisterType<SmsSender>().As<ISender>(); 
    } 
} 

internal class SmsSender : ISender{...} 

public class Foo() 
{ 
    Foo(ISender sender) 
    { 
     //as this is inside a AssemblyA thi should be resolved to type SmsSender 
     //SmsSender 
    } 
} 

-------- ------------------ コードAssemblyB ----------------------------

public class ComponentA: Module 
{ 
    protected override void Load(ContainerBuilder builder) 
    { 
     builder.RegisterType<EmailSender>().As<ISender>(); 
    } 
} 

internal class EmailSender : ISender{...} 

public class Bar() 
{ 
    Bar(ISender sender) 
    { 
     //as this is inside a AssemblyB this should be resolved to type EmailSender 
     //EmailSender 
    } 
} 

内部にはどうすれば要件を達成することができますか? 誰かが簡単な例を提供することで私を助けることができますか?

答えて

0

問題を解決するにはさまざまな方法がありますが、FooBarクラスを明示的に「教えて」、ISenderを使用する必要があります。これを行うには、「名前付きインスタンス」を使用できます。

まずMainAssemblyにこれらのコンポーネントへの参照がある場合、ComponentAとComponentBではアクセスできないため、ISenderインターフェイスはMainAssemblyに存在しないと仮定します。

あなたComponentAモジュール定義は、以下のようになります。

public class ModuleDefinition : Module 
{ 
    protected override void Load(ContainerBuilder builder) 
    { 
     const string emailSender = "EmailSender"; 

     builder.RegisterType<EmailSender>().As<ISender>().Named<ISender>(emailSender); 
     builder.RegisterType<Foo>() 
      .WithParameter((p, c) => p.Name == "sender", (p, c) => c.ResolveNamed<ISender>(emailSender)); 
    } 
} 

類推、ComponentBモジュール定義は次のようになります。

public class ModuleDefinition : Module 
{ 
    protected override void Load(ContainerBuilder builder) 
    { 
     const string smsSender = "SmsSender"; 

     builder.RegisterType<SmsSender>().As<ISender>().Named<ISender>(smsSender); 
     builder.RegisterType<Bar>() 
      .WithParameter((p, c) => p.Name == "sender", (p, c) => c.ResolveNamed<ISender>(smsSender)); 
    } 
} 

あなたが見ることができるように、私は明示的に設定しますISenderの実装はFooBarクラスの両方で使用する必要があります構成方法は.WithParameterです。

AFAIKこれを行うための暗黙の「アセンブリに基づく」方法はありません。

+0

アセンブリ間の間違った関係を指定しました。今私は質問を更新しました。申し訳ありません。あなたの答えはまだ有効ですか?私は何か変更を行う必要がありますか? – Rahul

+0

はい、答えは 'ISender'がMainAssemblyにあり、AssemblyAとAssemblyBがMainAssemblyへの参照を持っている場合に有効です – tdragon

+0

Foo&Barクラスが基本クラスから派生していて、もし私がAutofacで基底クラス型を解決する必要があれば?あなたの答えは次のようになります。 'builder.RegisterType () .WithParameter((p、c)...' – Rahul

関連する問題