简体   繁体   English

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

[英]Get multiple instances of an object registered via Autofac module registration

I have a use case where I need to get two copies of objects registered from Autofac module and pass them to register different types.我有一个用例,我需要从 Autofac 模块获取两个注册的对象副本并将它们传递给注册不同的类型。

In the below code sample,在下面的代码示例中,

  1. I want to pass an object of DataProtectionService with config dbConfig to register MyDbRepo .我想通过配置dbConfig的 DataProtectionService 的 object 来注册MyDbRepo
  2. Similarly, I want to pass an object of DataProtectionService with config cacheConfig to register MyCacheRepo .同样,我想通过配置 cacheConfig 的 DataProtectionService 的cacheConfig来注册MyCacheRepo

But, I am not sure how should I do that?但是,我不确定我应该怎么做? Am I missing something really basic here?我在这里错过了一些非常基本的东西吗?

I don't have an option to remove this DataProtectionServiceModule .我没有删除此DataProtectionServiceModule的选项。 Is there a way to achieve what I am expecting?有没有办法实现我的期望?

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();

You can use Keyed Services .您可以使用密钥服务 And then in your registration add a specific Resolve .然后在您的注册中添加一个特定的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
{
}

Alternatively you can use Named Services and the config-name dbConfig and cacheConfig .或者,您可以使用命名服务和配置名称dbConfigcacheConfig This way you do not need to change the constructor of DataProtectionServiceModule .这样您就不需要更改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")

And your module:你的模块:

    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);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM