我可以在启动时(.NET Core)在configservices方法中创建一个服务实例并向属性添加列表吗



我需要在新的.NET核心解决方案中将旧的VB.NET代码转换为c#。在旧代码中,他们使用Ninject模块。在其中一个模块中,他们创建一个服务实例,并向其中添加一个处理程序列表

Imports System.Collections.Generic
Imports AnC.Services.EventService.Shared.Interfaces ' for IEventHandler 
Class MyModule
Inherits NinjectModule ' See https://github.com/ninject/Ninject/wiki/Modules-and-the-Kernel 
Public Overrides Sub Load()
Dim es As New EventService(Me.Kernel.Get(Of IEventLogRepository), Me.Kernel.Get(Of IEventRepository), Me.Kernel.Get(Of ISelfInstallImportEdiOrder))
Dim handlers As New List(Of IEventHandler)

' (Add IEventHandler instances to `handlers` list here)
es.EventHandlers = handlers
Bind(Of EventService).ToConstant(es)
End Sub
End Class 

在新代码中,我想在StartUp类的ConfigureServices方法中做一些类似的事情,比如:

using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection.ServiceProvider; // for `ServiceProvider`
using AnC.Services.EventService.Shared.Interfaces; // for `IEventHandler`
void ConfigureServices( ServiceCollection services )
{
services.AddScoped<IEventRepository, EventRepository>();
services.AddScoped<IEventLogRepository, EventLogRepository>();
List<IEventHandler> handlers = new List<IEventHandler>();
// (Add IEventHandler instances to `handlers` list here)
ServiceProvider sp = services.BuildServiceProvider();
EventService    es = new EventService( sp.GetRequiredService<IEventLogRepository>(), sp.GetRequiredService<IEventRepository>() );
es.EventHandlers = handlers;
services.AddSingleton<IEventService,EventService>( sp => es );
}

我读到,调用services.BuildServiceProvider()是你最好避免的事情,因为可能存在单态的重复。在我的代码中,没有在这个调用之前注册的singleton。

这是我使用的正确方法吗?有更好的方法吗?

这在MS.DI:中是等效的

// NOTE: These are now singletons, because is EventService is singleton
// Please make sure you understand the concept of Captive Dependencies.
services.AddSingleton<IEventRepository, EventRepository>();
services.AddSingleton<IEventLogRepository, EventLogRepository>();
List<IEventHandler> handlers = new List<IEventHandler>();
// (Add IEventHandler instances to `handlers` list here)
services.AddSingleton<IEventService>(c =>
{
// Create EventService using Constructor Injection:
var es = new EventService(
c.GetRequiredService<IEventLogRepository>(),
c.GetRequiredService<IEventRepository>());
// Apply Property injection:
es.EventHandlers = handlers;
return es;
});

然而,更好的方法可能是放弃属性注入,转而使用构造函数注入来注入IEventHandler实现:

// EventService ctor:
public EventService(
IEventLogRepository eventLogRepo,
IEventRepository eventRepo,
IEnumerable<IEventHandler> handlers)

这导致以下注册:

services.AddSingleton<IEventRepository, EventRepository>();
services.AddSingleton<IEventLogRepository, EventLogRepository>();
// Add IEventHandler instances, e.g.:
services.AddSingleton<IEventHandler>(new EventHandler1());
services.AddSingleton<IEventHandler>(new EventHandler2());
services.AddSingleton<IEventHandler>(new EventHandler3());
services.AddSingleton<IEventHandler, EventHandler4>();
services.AddSingleton<IEventService, EventService>();

这种方法的优点是,它允许在容器中注册IEventHandler实现。这允许处理程序获得自己的依赖项,并将其注入到构造函数中,这是您可以在上一个示例中的EventHandler4注册中看到的。

请防止在代码中的任何位置调用BuildServiceProvider,因为这可能会导致大量问题,如本文所述。

最新更新