繁体   English   中英

在.NET Core Service应用程序中使用依赖注入

[英]Using Dependency Injection in .NET Core Service application

我们在.net核心中有一个基于服务的应用程序,它将在Linux环境中作为守护程序运行。 一切都按预期工作,但我在处理依赖项注入时遇到问题。 下面是参考代码

Program.cs中

class Program
{
    static async Task Main(string[] args)
    {
        Console.WriteLine("Starting PreProcessor Application ");


        try
        {
            ConfigParameters.LoadSettings(args);

        }
        catch (Exception ex)
        {

            Console.BackgroundColor = ConsoleColor.Red;
            Console.WriteLine($"Error in setting config parameters {ex.Message}");
            return;
        }            

        IHost host = new HostBuilder()

            .ConfigureServices((hostContext, services) =>
            {
                services.AddLogging();                    
                services.AddHostedService<MainService>();
                services.AddTransient<IMessageQueue, ActiveMQHandler>(x =>
                {
                    return new ActiveMQHandler(ConfigParameters.Settings.MessageQueueAddress);
                });
                services.AddTransient<IMessageQueue, ActiveMQHandler>(x =>
                {
                    return new ActiveMQHandler(ConfigParameters.Settings.MessageQueueAddress);
                });
                services.AddTransient<IMessageQueue, ActiveMQHandler>(x =>
                {
                    return new ActiveMQHandler(ConfigParameters.Settings.MessageQueueAddress);
                });
            })
            .Build();        

        await host.RunAsync();
    }
}

MainService构造函数如下所示

IApplicationLifetime appLifetime;
    IConfiguration configuration;
    PreProcessorQueueListener listener;
    private string reason = "SHUTDOWN SIGNAL";
    private IMessageQueue messageQueue;
    private IMessageQueue messageQueueSL;
    private IMessageQueue messageQueueSLProcess;
    public MainService(IConfiguration configuration, IApplicationLifetime appLifetime, IMessageQueue messageQueue, IMessageQueue messageQueueSL, IMessageQueue messageQueueSLProcess)
    {
        this.configuration = configuration;            
        this.messageQueue = messageQueue;
        this.messageQueueSL = messageQueueSL;
        this.messageQueueSLProcess = messageQueueSLProcess;
        this.appLifetime = appLifetime;
    }

如果您在MainService代码中看到,我正在使用构造函数依赖项注入为IMessageQueue接口传递三个实例。 我真正想要的是基于应用程序任何部分的需求,我可以通过传递IMessageQueue接口来获取ActiveMQHandler类的新实例。 由于我无法为此找到解决方案,因此我传递了三个IMessageQueue实例(对此解决方案我不满意)。 如果我需要使用的其他实例ActiveMQHandler类,那么我将不得不第四个参数为传递IMessageQueue接口在我MainService类。

我真正在寻找的是使用ServiceProvider (或更优雅的东西),并使用它来获取实现IMessageQueue接口的类的新实例/单例(基于Program.cs定义)。

一个建议的家伙?

如果将MainService构造函数签名更改为

public MainService(IConfiguration configuration, IApplicationLifetime appLifetime, IEnumerable<IMessageQueue> messageQueues)

您将能够访问所有三个接口实现。

问题可能在于是否需要从列表中识别它们,例如对每个实现执行不同的操作。 如果您需要对每个实现执行相同的操作,那么它将起作用。

否则,您应该考虑使用通用类型来区分注入的实现。

只需将构造函数更改为包含IEnumerable<IMessageQueue> 它应该为您提供所有已注册IMessageQueue实现者的列表。

我个人不喜欢在类中依赖IApplicationLifetime或IServiceProvider。 这有点像ServiceLocator反模式。

您可以将IServiceProvider注入到类中,然后使用Microsoft.Extensions.DependencyInejction命名空间中的GetServices(typeof(IMessageQueue))或扩展函数GetServices<IMessageQueue>() 所以像这样:

public MainService(IConfiguration configuration, IApplicationLifetime appLifetime, IServiceProvider serviceProvider)
{
    this.configuration = configuration;            
    messageQueue = serviceProvider.GetServices<IMessageQueue>();
    messageQueueSL = serviceProvider.GetServices<IMessageQueue>();
    messageQueueSLProcess = serviceProvider.GetServices<IMessageQueue>();
    this.appLifetime = appLifetime;
}

根据您使用IMessageQueue确切目的,可能会有更优雅的解决方案。 似乎IMessageQueue用于某种日志记录。 例如,假设您需要为SLProcessSL是不同类的每个类SLProcess一个消息队列。 对于这种情况,您可以注入泛型。 因此,您可以定义以下内容:

interface IMessageQueue<T> : IMessageQueue { }

class ActiveMQHandler<T> : ActiveMQHandler, IMessageQueue<T> {

    public string targetType => typeof(T).ToString();
}

有了这个,您应该能够注入如下内容: AddTransient(typeof(IMessageQueue<>), typeof(ActiveMQHandler<>))

最后,我提供了一个我认为很优雅且不依赖于构造函数DI的解决方案。 想法是让服务(是的,我们有一个微服务体系结构)在IServiceCollection创建依赖关系的集合,一旦服务启动,只要任何类想要解析依赖关系,它们都将传入Interface并获取具体实例。类。 我的最终代码是这样的。 我在公共库中创建了一个单独的类

public class DependencyInjection
{
    private static ServiceProvider Provider;
    public static void AddServices(IServiceCollection services)
    {
        Provider = services.BuildServiceProvider();
    }

    public static T GetService<T>()
    {
        var serviceScopeFactory = Provider.GetRequiredService<IServiceScopeFactory>();
        using (var scope = serviceScopeFactory.CreateScope())
        {
            return scope.ServiceProvider.GetService<T>();
        }
    }
}

现在我在Program.cs文件中的Main方法看起来像这样

static async Task Main(string[] args)
    {
        Console.WriteLine("Starting PreProcessor Application ");
        IServiceCollection servicesCollection = new ServiceCollection();

        try
        {
            ConfigParameters.LoadSettings(args);
            servicesCollection.AddScoped<IMessageQueue, ActiveMQHandler>(x =>
            {
                return new ActiveMQHandler("127.0.0.1");
            });
            DependencyInjection.AddServices(servicesCollection);
        }
        catch (Exception ex)
        {

            Console.BackgroundColor = ConsoleColor.Red;
            Console.WriteLine($"Error in setting config parameters {ex.Message}");
            return;
        }

        IHost host = new HostBuilder()
            .ConfigureHostConfiguration(configHost =>
            {
                configHost.AddCommandLine(args);
            })
            .ConfigureServices((hostContext, services) =>
            {
                services.AddLogging();
                services.AddHostedService<MainService>();                    
            })
            .Build();            

        await host.RunAsync();
    }

现在在项目中的任何地方,当我需要ActiveMQHandler类的实例时,我只需编写以下代码行

var messageQueue = DependencyInjection.GetService<IMessageQueue>();

只是在我的信息Program.cs我使用AddScoped但我已经测试了代码AddSingleton也和每次我要求的具体类实例是相同的。

此链接上的文章https://stackify.com/net-core-dependency-injection/帮助了我

暂无
暂无

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

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