使用带有类型参数的.NET Core内置DI替换Ninject

时间:2017-03-23 02:44:52

标签: c# dependency-injection asp.net-core

我有一个旧的.NET应用程序,它使用Ninject来解析ICommandHandler的一个实例,如下所示。我还使用Db上下文来调用SaveChanges()。我现在正在尝试转换此代码,以便我可以在具有内置依赖注入的新.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();
        }
    }

我认为我必须将以下内容添加到Startup.cs中的ConfigureServices方法中:

services.AddScoped<ICommandHandler, CommandHandler>();

但是ICommandHandler有一个类型参数。如何完成或注册?

其次,我需要解决它以创建执行命令的处理程序。如何在.NET Core中解决这个问题?

P.S。我不想在我的.NET Core应用程序中继续使用Ninject。

2 个答案:

答案 0 :(得分:0)

根据LukeHutton给出的答案,注册使用:

services.AddScoped(typeof(ICommandHandler<>), typeof(CommandHandler<>));

要解决:

// 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>>();

答案 1 :(得分:0)

我经历了同样的问题,我创建了一些事件处理结构来解决Asp.NET Core 2.0上的这个问题。 我创建了一个事件registrator来映射事件处理程序:

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;
            }
        }
    }
}

以下编码将添加到启动中:

    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);
}

然后是调解员(派遣或举起事件的对象):

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);
        }
    }
}

缺少的接口:

    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();
}