web-dev-qa-db-ja.com

Moduleクラス内のAutoFac依存関係の解決

私はAutoFacを初めて使用し、現在、アプリ構成内のカスタムモジュールを使用して、いくつかのコアF#システムを起動しています。私が使用しているコードは

var builder = new ContainerBuilder();
builder.RegisterType<DefaultLogger>().As<IDefaultLogger>();
builder.RegisterModule(new ConfigurationSettingsReader("autofac"));
builder.Build();

また、アプリ構成内には、関連するシステムを起動するための適切なロジックがあります。モジュール内のDefaultLoggerにアクセスしたいのですが。 Module基本クラスのメタデータには、次のオプションがあります。

protected virtual void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration);

protected virtual void AttachToRegistrationSource(IComponentRegistry componentRegistry, IRegistrationSource registrationSource);

public void Configure(IComponentRegistry componentRegistry);

protected virtual void Load(ContainerBuilder builder);

私はこれまでLoadを使用しているだけで、ロギングサービスを利用できるビルダーのメソッドが見つかりません。

15
Jesse Carter

答えは信じられないほど単純であることが判明しました。モジュールの実装への依存関係としてIComponentContextを追加しました

public class LocalActorSystemModule : Module {
    private IComponentContext m_ComponentContext; // A service for resolving dependencies required by this module

    public LocalActorSystemModule(IComponentContext componentContext) { 
        m_ComponentContext = componentContext;
    }

そして、AutoFacにIComponentContextを挿入させてください。そうすれば、モジュール内で必要な依存関係を解決できます。

3
Jesse Carter

RegisterTypeメソッドを使用する代わりにautofacを使用してモジュール内に何かを登録する場合は、Registerメソッドを使用できます。

builder.Register(c =>
   {
       IComponentContext ctx = c.Resolve<IComponentContext();
       IDefaultLogger logger = ctx.Resolve<IDefaultLogger>();
       ...do something with logger...
       return ...return object you want to register...;
    });
6
mr100

すべてのIoC/DIコンテナを使用するための経験則:一度解決してください!=>その後、すべてを取得します要求されたオブジェクトの依存関係が解決されました。複数回解決しようとする場合は、(その間に)地獄で立ち往生している他のオブジェクトを登録してください。本当に。さまざまな場所と時点でさまざまな目的でオブジェクトを取得する場合(中央登録から解決)、代わりに サービスロケーターパターン を探すことができます(ただし、これは多くの場合 アンチパターン も)。

モジュールには、関連する登録を(条件付きで)状態としてバンドルする目的があります Autofacドキュメント

モジュールは、構成と展開を簡素化するために「ファサード」の背後に関連するコンポーネントのセットをバンドルするために使用できる小さなクラスです。

...したがって、それらが単なる登録の合計であり、コンテナがまだビルドされていない場合、(以前に登録されていても)コンポーネントをすぐに解決して使用することはできません(OnActivate *フックまたはインスタンス登録を使用する場合ですが、これはあなたの例には当てはまらないと思います)。コンポーネントは登録状態にありますが、完全なコンテキストを解決する準備ができていません。別のモジュールの登録を上書きするとどうなりますか?次に、さまざまなオブジェクトを注入します...悪い考えです。たぶん、アプリケーションの設計と、どのオブジェクトがどの責任を持っているかを再考する必要があります。

ちなみに、ロギングは横断的関心事であり、コンストラクター/プロパティの注入を行う代わりに、別の静的ファクトリまたはサービスを呼び出すことによって「注入/解決」されることがよくあります(たとえば Common.Logging の使用法を参照) 。

public class MyModule : Module
{
    private static readonly ILog Log = LogManager.GetLogger<MyModule>();

    protected override void Load(ContainerBuilder builder)
    {
        Log.Debug(msg => msg("Hello")); // log whatever you want here
    }
}

[〜#〜] aop [〜#〜]ライブラリを使用して、依存関係をモジュールに織り込むこともできます(リフレクションを使用)。しかし、モジュールにログインするためだけに試す価値はないと思います。

とにかく:@ mr100は、登録時にすでに正しい使用法を示しています。そこでは、アクティベーションなどを処理することもできますが、モジュール自体のロギングは実行できません。

2
Beachwalker