。Net Core DI将运行时参数传递给服务的构造函数,也传递给其子服务的1-n

问题描述 投票:0回答:1

我有多个流程服务。这些服务具有我需要在使用特定服务之前填写的属性。但是,这些过程服务还使用1-n生成器子服务,该子服务也具有与过程服务相同的属性。

public interface IProcess
{
    IEnumerable<string> metadata;
    //...
}

public class Process1 : IProcess
{
    public IEnumerable<string> Metadata {get; set;}
    private readonly IGenerator1 Generator1;
    private readonly IGenerator2 Generator2;

    public Process1(
        IGenerator1 generator1,
        IGenerator2 generator2,
        IEnumerable<string> metadata)
    {
        Generator1 = generator1;
        Generator2 = generator2;
        Metadata = metadata;
    }
}

public interface IGenerator
{
    IEnumerable<string> metadata;
    //...
}

public class Generator1 : IGenerator
{
    public IEnumerable<string> Metadata {get; set;}
    private readonly ILogger Logger;

    public Generator1(
        ILogger logger,
        IEnumerable<string> metadata)
    {
        Logger = logger;
        Metadata = metadata;
    }
}

我使用DI并解决ServiceBuilder中的依赖项

public class ServiceBuilder
{
    public ServiceBuilder()
    {
        var services = new ServiceCollection();

        services.AddTransient<IProcess, Process1>();
        services.AddSingleton<IProcessFactory, ProcessFactory>();
        services.AddTransient<IDeliverySiteGenerator, DeliverySiteGenerator>();
        services.AddTransient<INewConnectionErrandGenerator, NewConnectionErrandGenerator>();
        //...
        ServiceProvider = services.BuildServiceProvider();
    }
}

并使用ProcessFactory类及其'方法GetProcess来检索我要使用的进程。我将这些进程添加到List<IProcess>中,然后使用此列表从所有检索到的IProcess服务中执行特定方法。 configData由用户输入提供,并且还包括我们想要的属性IEnumerable<string> Metadata

public class ProcessFactory : IProcessFactory
{
    private readonly IServiceProvider serviceProvider;
    //...
    public IProcess GetProcess(SomeConfigData configData)
    {
        var processExists = registeredProcesses.TryGetValue(configData, out var processType);

        if (!processExists)
            throw new InvalidArgumentException($"Process not supported.");

        return (IProcess)serviceProvider.GetService(processType);
    }
}

[现在,当Metadata具有公共设置器时,通过GetProcess方法检索到Metadata后,将其添加到IProcess服务。但这并不能解决如何将其传递给生成器子服务的问题。不想遍历流程服务的所有生成器实例,并通过公共设置器添加Metadata。有什么办法可以做到这一点?

c# .net-core dependency-injection constructor parameter-passing
1个回答
0
投票

一种方法是创建范围服务以提供对元数据的访问:

public interface IMetadataAccessor
{
    IEnumerable<string> Metadata { get; set; }
}

public class MetadataProcessor : IMetadataAccessor
{
    public IEnumerable<string> Metadata { get; set; }
}

将服务注册为范围:

serviceCollection.AddScoped<IMetadataAccessor, MetadataProcessor>();

更改流程和生成器类以通过构造函数注入IMetadataAccessor,并读取像这样的元数据:

public IEnumerable<string> Metadata => _metadataAccessor.Metadata;

更改工厂以在范围内实例化处理器:

public Processor CreateProcessor(IEnumerable<string> metadata)
{
    // Resolve services within a child scope
    using (var scope = _services.CreateScope())
    {
        // Resolve the accessor service and set metadata
        var accessor = scope.ServiceProvider.GetRequiredService<IMetadataAccessor>();
        accessor.Metadata = metadata;

        // Within the current scope, there is only one IMetadataAccessor.
        // So both process and generator will be getting same accessor instance via the constructor.
        // If we set metadata to the instance, all services can get the value.
        var process = scope.ServiceProvider.GetRequiredService<Process>();
        return process;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.