如何让Autofac将同一类的不同唯一初始化实例注入不同的控制器?

Tri*_*Gao 2 autofac

我有2个控制器,都需要一个MySettings代表一组设置的对象.每个控制器都需要其自定义设置集.为了在模块注册时执行此操作,我手动创建了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;
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望一定有更好的方法.

UPDATE2:

解决这一不足的另一种方法是根据MySettings类创建2个新类设置.这样每个实例唯一对应一个类,Autofac可以轻松解决它.我不想仅仅为了使Autofac工作.

nem*_*esv 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"));
Run Code Online (Sandbox Code Playgroud)

但是,此解决方案需要在注册期间列出所有控制器命名的参数对,这可能容易出错.

另一种方法是,您不直接依赖于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());
    }
}
Run Code Online (Sandbox Code Playgroud)

并相应注册:

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>();
Run Code Online (Sandbox Code Playgroud)

你应该注意,你可以使用任何东西,Keyed而不仅仅是Type你可以识别哪个控制器应该获得哪些设置,如字符串,枚举等.

  • 然后,您仍然可以使用命名注册,但您需要以不同方式标识实例,例如通过custructor参数的名称.顺便说一下,这也是一种气味,你想从容器中解决两个相同类型的问题... IoC容器用于注册和解析服务而不是用于构建数据...但是我会用一个更新我的答案不同的方法 (3认同)