首页 > 解决方案 > 如何注入 IEnumerable这也是作为单例生命周期的托管服务

问题描述

我希望利用 .Net Core 来处理与整个应用程序相同的服务的生命周期,我想将它们注入另一个托管服务。我知道我可以自己在服务器的启动/停止中实现侦听器的启动/停止。但是,如果我可以在下面的场景中工作,那感觉没有必要。

我宁愿将其简化为一行以进行注册。我正在为 IServiceCollection 创建扩展方法。

public class Server: IHostedService
{
    public Server(IEnumerable<IConnectionListener> listeners)
    {
        foreach(var l in listeners) 
        {
            l.Connected += HandleConnection;
        }
    }

    private void HandleConnection(object src, Foo foo) { }

    public async Task StartAsync(CancellationToken ct)
    {}

    public async Task StopAsync(CancellationToken ct)
    {}
}


public interface IConnectionListener
{
    event ConnectionHandler Connected;
}

public class ConnectionListener: BackgroundService, IConnectionListener
{
    public async Task ExecuteAsync(CancellationToken ct)
    {
         // Open TcpListener and register with the ct to stop the listener.
    }
}

public class SslConnectionListener: BackgroundService, IConnectionListener
{
    public async Task ExecuteAsync(CancellationToken ct)
    {
         // Open TcpListener and register with the ct to stop the listener.
         // Add some extra SSL stuff
    }
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureServices((hc, services) => 
        {
            // This appears to work. But I have concerns about whether the life times will truly
            // be singleton and automatic disposal of the objects (having used the factory, I do
            // want the automatic disposal by the container).
            var listener = new ConnectionListener();
            var sslListener = new SslConnectionListener();
            services.AddSingleton<IConnectionListener>(sp => listener);
            services.AddSingleton<IConnectionListner>(sp => sslListener);

            services.AddHostedService(sp => listener);
            services.AddHostedService(sp => sslListener);

            // This doesn't work
            services.AddHostedService<SslConnectionListener>();
            services.AddHostedService<ConnectionListener>()
            services.AddHostedService<Server>();
        }

标签: c#.net-coredependency-injection

解决方案


你可以考虑这种方法

//register the instances
services.AddSingleton<ConnectionListener>();
services.AddSingleton<SslConnectionListener>();
//register their abstractions
services.AddSingleton<IConnectionListener>(sp => sp.GetService<ConnectionListener>());
services.AddSingleton<IConnectionListener>(sp => sp.GetService<SslConnectionListener>());
//register hosted services.
services.AddHostedService(sp => sp.GetService<ConnectionListener>());
services.AddHostedService(sp => sp.GetService<SslConnectionListener>());
services.AddHostedService<Server>();

通过这种方式,容器管理所创建实例的整个生命周期。

这可以巧妙地包装在扩展方法中以简化调用。


推荐阅读