[英]Replace Ninject with .NET Core built-in DI with typed parameters
I have an old .NET application that uses Ninject to resolve an instance of an ICommandHandler as shown below. 我有一个旧的.NET应用程序,该应用程序使用Ninject解析ICommandHandler的实例,如下所示。 I also uses the Db context to call SaveChanges().
我还使用Db上下文调用SaveChanges()。 I'm now trying to convert this code so that I can use it in a new .NET Core application with its built-in Dependency Injection.
我现在正在尝试转换此代码,以便可以在具有内置依赖关系注入的新.NET Core应用程序中使用它。
public class CommandInvoker : ICommandInvoker
{
private readonly IKernel _kernel;
private readonly IArhomaContext _context;
public CommandInvoker(IKernel kernel, IArhomaContext context)
{
_kernel = kernel;
_context = context;
}
public void Execute<T>(T command)
{
var handler = _kernel.TryGet<ICommandHandler<T>>();
handler.Handle(command);
_context.SaveChanges();
}
}
I'm thinking that I have to add the following to the ConfigureServices method in Startup.cs: 我在想我必须在Startup.cs的ConfigureServices方法中添加以下内容:
services.AddScoped<ICommandHandler, CommandHandler>();
But ICommandHandler has a typed parameter. 但是ICommandHandler具有类型化的参数。 How is that done or registered?
如何完成或注册?
Secondly, I need to resolve it to create a handler that executes the command. 其次,我需要解决它才能创建一个执行命令的处理程序。 How does one resolve this in .NET Core?
如何在.NET Core中解决此问题?
PS I do not want to continue using Ninject in my .NET Core app. PS我不想在我的.NET Core应用程序中继续使用Ninject。
based on the answer LukeHutton gave, to register use: 根据LukeHutton给出的答案,进行注册使用:
services.AddScoped(typeof(ICommandHandler<>), typeof(CommandHandler<>));
To resolve: 解决:
// You should only Build the provider once in your code, to do so:
var provider = services.BuilderServiceProvider(); //to protect against runtime injection, which is an anti-pattern
// to Get an Actual ICommandHandler
var commandHandler = services.GetService<ICommandHandler<MyT>>();
I went through the same issue, and I created some event handling structure to solve this issues on Asp.NET Core 2.0. 我经历了同样的问题,并创建了一些事件处理结构来解决Asp.NET Core 2.0上的此问题。 I created a event registrator that mapps the event handlers :
我创建了一个映射事件处理程序的事件注册器:
public class EventRegistrator : IEventRegistrator
{
private readonly IDictionary<Type, IList<Type>> dictionary = new Dictionary<Type, IList<Type>>();
public IEventRegistrator Add<Event, Handler>()
where Event : IEvent
where Handler : IEventHandler<Event>
{
var eventType = typeof(Event);
var handlerType = typeof(Handler);
if (!dictionary.ContainsKey(eventType))
{
dictionary[eventType] = new List<Type>();
}
dictionary[eventType].Add(handlerType);
return this;
}
public IEnumerable<Type> GetHandlers<Event>()
where Event : IEvent
{
if (dictionary.TryGetValue(typeof(Event), out IList<Type> handlers))
{
return handlers;
}
return new List<Type>();
}
public IEnumerable<Type> GetHandlers()
{
foreach (var item in dictionary)
{
foreach (var handler in item.Value)
{
yield return handler;
}
}
}
}
The following coded would be added to the startup : 以下代码将添加到启动中:
var registrator = new EventRegistrator()
.Add<TrainerCreatedEvent, ProcessionalWelcomeMessageHandler>()
.Add<TrainerCreatedEvent, ProfessionalCreatedCertificationStartHandler>();
services.AddSingleton<IEventRegistrator>(context =>
{
return registrator; // All Event Handlers should be handled here
});
foreach (var handler in registrator.GetHandlers())
{
services.AddTransient(handler);
}
Then the mediator ( the objects that dispatch or raise the event ) : 然后是中介者(调度或引发事件的对象):
public class SimpleMediator : IMediator
{
private readonly IServiceProvider provider;
private readonly IEventRegistrator registrator;
public SimpleMediator(IEventRegistrator registrator, IServiceProvider provider)
{
this.registrator = registrator;
this.provider = provider;
}
public async Task Dispatch<T>(T target)
where T : IEvent
{
var handlers = registrator.GetHandlers<T>();
if (handlers == null) return;
foreach (Type item in handlers)
{
var instance = (IEventHandler<T>)provider.GetService(item);
if (instance == null) throw new NullReferenceException($"No type {item.ToString()} has been registred on the service collections. Add this type to the service collections.");
await instance.HandleAsync(target);
}
}
}
The missing interfaces : 缺少的接口:
public interface IMediator
{
Task Dispatch<T>(T target)
where T : IEvent;
}
public interface IEventRegistrator
{
/// <summary>
/// Register a handler to the event. Multiple handlers are supported
/// </summary>
IEventRegistrator Add<Event, Handler>()
where Event : IEvent
where Handler : IEventHandler<Event>;
/// <summary>
/// Returns all handlers to a event
/// </summary>
IEnumerable<Type> GetHandlers<Event>() where Event : IEvent;
/// <summary>
/// Returns all handlers of all registered events.
/// </summary>
IEnumerable<Type> GetHandlers();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.