获取通过 Autofac 模块注册注册的对象的多个实例

Get multiple instances of an object registered via Autofac module registration

我有一个用例,我需要从 Autofac 模块中获取两个对象的副本并传递它们以注册不同的类型。

在下面的代码示例中,

  1. 我想通过配置 dbConfig 传递一个 DataProtectionService 对象来注册 MyDbRepo
  2. 同样,我想通过配置cacheConfig传递一个DataProtectionService对象来注册MyCacheRepo

但是,我不确定该怎么做?我在这里错过了一些非常基本的东西吗?

我没有删除此 DataProtectionServiceModule 的选项。有什么方法可以实现我的期望吗?

public class DataProtectionServiceModule : Module
{
    private readonly string config;

    public DataProtectionServiceModule(string config)
    {
        this.config = config;
    }

    protected override void Load(ContainerBuilder builder)
    {
        builder.Register<Token>(compContext =>
        { // a complex logic here
        }).OnRelease(instance => instance.Dispose());

        builder.Register(c =>
        {
            // a logic to generate an object of IDataProtectionService
            // this logic involves the use of config field of this class.
        }).As<IDataProtectionService>();
    }
}

public class MyDbRepo : IMyDbRepo
{
    IDataProtectionService dataProtectionService;
    public MyDbRepo(IDataProtectionService dataProtectionService)
    {
        this.dataProtectionService = dataProtectionService;
    }
}

public class MyCacheRepo : IMyCacheRepo
{
    IDataProtectionService dataProtectionService;
    public MyCacheRepo(IDataProtectionService dataProtectionService)
    {
        this.dataProtectionService = dataProtectionService;
    }
}

// Program.cs of my backend micro service
var builder = new ContainerBuilder();
builder.RegisterModule(new DataProtectionServiceModule("dbConfig"));
builder.RegisterModule(new DataProtectionServiceModule("cacheConfig")); // I have figured, this is wrong.
builder.RegisterType<MyDbRepo>().As<IMyDbRepo>().SingleInstance();
builder.RegisterType<MyCacheRepo>().As<IMyCacheRepo>().SingleInstance();

您可以使用 Keyed Services。然后在您的注册中添加特定的 Resolve.

    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");


        // Program.cs of my backend micro service
        var builder = new ContainerBuilder();
        builder.RegisterModule(new DataProtectionServiceModule("dbConfig", DeviceState.Db));
        builder.RegisterModule(new DataProtectionServiceModule("cacheConfig", DeviceState.Cache)); // I have figured, this is wrong.
        builder.RegisterType<MyDbRepo>().WithParameter(
            new ResolvedParameter(
                (pi, ctx) => pi.ParameterType == typeof(IDataProtectionService),
                (pi, ctx) => ctx.ResolveKeyed<IDataProtectionService>(DeviceState.Db)
            )
        ).As<IMyDbRepo>().SingleInstance();
        builder.RegisterType<MyCacheRepo>().WithParameter(
            new ResolvedParameter(
                (pi, ctx) => pi.ParameterType == typeof(IDataProtectionService),
                (pi, ctx) => ctx.ResolveKeyed<IDataProtectionService>(DeviceState.Cache)
            )
        ).As<IMyCacheRepo>().SingleInstance();

        var container = builder.Build();

        var cache = container.Resolve<IMyCacheRepo>();
        var db = container.Resolve<IMyDbRepo>();

    }
}

public enum DeviceState { Cache, Db }


public class DataProtectionServiceModule : Module
{
    private readonly string config;
    private readonly DeviceState _state;

    public DataProtectionServiceModule(string config, DeviceState state)
    {
        this.config = config;
        _state = state;
    }

    protected override void Load(ContainerBuilder builder)
    {
        builder.Register<Token>(compContext =>
        { // a complex logic here
        }).OnRelease(instance => instance.Dispose());

        builder.Register(c =>
        {
            // a logic to generate an object of IDataProtectionService
            // this logic involves the use of config field of this class.
            return new DataProtectionService(config);
        }).Keyed<IDataProtectionService>(_state);
    }
}

public class DataProtectionService : IDataProtectionService
{
    public string Config { get; }

    public DataProtectionService(string config)
    {
        Config = config;
    }
}


public class MyDbRepo : IMyDbRepo
{
    IDataProtectionService dataProtectionService;
    public MyDbRepo(IDataProtectionService dataProtectionService)
    {
        this.dataProtectionService = dataProtectionService;
    }
}

public interface IDataProtectionService
{
}

public interface IMyDbRepo
{
}

public class MyCacheRepo : IMyCacheRepo
{
    IDataProtectionService dataProtectionService;
    public MyCacheRepo(IDataProtectionService dataProtectionService)
    {
        this.dataProtectionService = dataProtectionService;
    }
}

public interface IMyCacheRepo
{
}

或者您可以使用 Named Services 和配置名称 dbConfigcacheConfig。这样您就不需要更改 DataProtectionServiceModule.

的构造函数
    builder.RegisterType<MyDbRepo>().WithParameter(
        new ResolvedParameter(
            (pi, ctx) => pi.ParameterType == typeof(IDataProtectionService),
            (pi, ctx) => ctx.ResolveNamed<IDataProtectionService>("dbConfig")
        )
    ).As<IMyDbRepo>().SingleInstance();
    builder.RegisterType<MyCacheRepo>().WithParameter(
        new ResolvedParameter(
            (pi, ctx) => pi.ParameterType == typeof(IDataProtectionService),
            (pi, ctx) => ctx.ResolveNamed<IDataProtectionService>("cacheConfig")

你的模块:

    protected override void Load(ContainerBuilder builder)
    {
        //builder.Register<Token>(compContext =>
        //{ // a complex logic here
        //}).OnRelease(instance => instance.Dispose());

        builder.Register(c =>
        {
            // a logic to generate an object of IDataProtectionService
            // this logic involves the use of config field of this class.
            return new DataProtectionService(config);
        }).Named<IDataProtectionService>(config);
    }