2

MySettings私は 2 つのコントローラーを持っていますが、どちらも一連の設定を表すタイプのオブジェクトを必要とします。各コントローラには、独自の設定セットが必要です。これを行うには、モジュールの登録時に 2 つの設定オブジェクトを手動で作成し、両方をコンテナーに配置します。質問は、各コントローラーに MySettings 型の独自の事前定義されたカスタム初期化インスタンスを挿入するように指定するにはどうすればよいですか?

アップデート:

現在、すべての解決が手動で行われるため、基本的にAutofacを役に立たなくする醜い回避策があります。

public class MyModule : Module {
    protected override void Load(ContainerBuilder builder) {
        builder.Register(context => {
            var productControllerSettings = new MyListSettings(
                pageSize: 20,
                orderBy: "Name",
                orderDirection: OrderDirection.Ascending
            );
            // and hell of other parameters that I need to resove
            // by hands by doing context.Resolve<...> for each of them
            var productController = new ProductController(
                productControllerSettings
                /*, the reset of parameters */
            );
            return productController;
        });

        builder.Register(context => {
            var userControllerSettings = new MyListSettings {
                pageSize: 20,
                orderBy: "LastName",
                orderDirection: OrderDirection.Ascending
            };
            var userController = new UserController(
                userControllerSettings
                /*, the rest of parameters resolved by calling context.Resolve<> by hands */
            );
            return userController;
        });
    }
}

もっと良い方法があるはずです。

更新 2:

この不足を回避する別の方法は、MySettings クラスに基づいて 2 つの新しい設定クラスを作成することです。このようにして、各インスタンスはクラスに一意に対応し、Autofac はそれを簡単に解決できます。Autofac を機能させるためだけにやりたいわけではありません。

4

2 に答える 2

9

最も簡単な解決策は、AutofacのNamed登録機能を使用することです。

そのため、MyControllerSettingsインスタンスに名前を付けて登録し、コントローラーを登録するときにこの名前をパラメーターとして使用します。

var productControllerSettings = new MyListSettings(
    pageSize: 20,
    orderBy: "Name",
    orderDirection: OrderDirection.Ascending);

builder.RegisterInstance(productControllerSettings)
       .Named<MyListSettings>("productControllerSettings");

var userControllerSettings = new MyListSettings(
        pageSize: 20,
        orderBy: "LastName",
        orderDirection: OrderDirection.Ascending);
builder.RegisterInstance(userControllerSettings)
       .Named<MyListSettings>("userControllerSettings");

builder.RegisterType<ProductController>()
    .WithParameter(
        ResolvedParameter.ForNamed<MyListSettings>("productControllerSettings"));

builder.RegisterType<UserController>()
    .WithParameter(
        ResolvedParameter.ForNamed<MyListSettings>("userControllerSettings"));

ただし、このソリューションでは、エラーが発生しやすい登録中にすべてのコントローラーと名前付きパラメーターのペアをリストする必要があります。

MyListSettings別のアプローチは、コントローラーではなく "MyListSettings" プロバイダーに直接依存することです。このプロバイダーを具象クラスとして持つことも、Autofac の組み込みのリレーション タイプIIndex使用して軽量プロバイダーを作成することもできます。

したがって、コントローラーは次のようになります。

public class ProductController
{
    private readonly MyListSettings productControllerSettings;

    public ProductController(Func<Type, MyListSettings> settingsProvider)
    {
        this.productControllerSettings = settingsProvider(GetType());
    }
}

public class UserController
{
    private readonly MyListSettings userControllerSettings;

    public UserController(Func<Type, MyListSettings> settingsProvider)
    {
        this.userControllerSettings = settingsProvider(GetType());
    }
}

対応する登録:

var productControllerSettings = new MyListSettings(
    pageSize: 25,
    orderBy: "Name",
    orderDirection: OrderDirection.Ascending);

builder.RegisterInstance(productControllerSettings)
       .Keyed<MyListSettings>(typeof (UserController1));

var userControllerSettings = new MyListSettings(
    pageSize: 20,
    orderBy: "LastName",
    orderDirection: OrderDirection.Ascending);

builder.RegisterInstance(userControllerSettings)
       .Keyed<MyListSettings>(typeof (ProductController1));

//register the provider func
builder.Register<Func<Type, MyListSettings>>(
    c => (t) => c.Resolve<IIndex<Type, MyListSettings>>()[t]);

builder.RegisterType<ProductController>();
builder.RegisterType<UserController>();

文字列、列挙型など、どのコントローラーがどの設定を取得する必要があるかを特定するためにできることKeyedだけでなく、何でも使用できることに注意してください。Type

于 2013-09-22T17:32:02.417 に答える
0

もう 1 つの方法は、AutoFac のメタデータ機能を使用することです。

public UserController(IEnumerable<Meta<ISettings>> allSettings)
{
    this.settings = allSettings.Where(s => ....);
}

これにより、複数の設定オブジェクトを取得し、それぞれに提供されたメタデータに基づいて必要なものを選択できます。

于 2013-09-22T19:20:23.957 に答える