c# - 使用ctor注入(inject)和ServiceProvider创建实例

标签 c# dependency-injection .net-core inversion-of-control

我知道有 IServiceCollection 接口(interface),我可以在其中注册我的服务,还有 IServiceProvider 可以实例化服务。

如何根据指定的类型实例化一个使用注册服务的类?

class MyClass
{
    public MyClass(ISomeService someService) { }
}

var serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<ISomeService, SomeService>()

MyClass instance = CreateInstance(typeof(MyClass));

object CreateIntance(Type type)
{
   ???
}

例如,ASP.NET Core 如何创建 Controller 实例?

我已经简单地实现了激活器,但是 .NET Core 中不是已经有类似的东西了吗?

private static object CreateInstance(Type type, IServiceProvider serviceProvider)
{
    var ctor = type.GetConstructors()
        .Where(c => c.IsPublic)
        .OrderByDescending(c => c.GetParameters().Length)
        .FirstOrDefault()
        ?? throw new InvalidOperationException($"No suitable contructor found on type '{type}'");

    var injectionServices = ctor.GetParameters()
        .Select(p => serviceProvider.GetRequiredService(p.ParameterType))
        .ToArray();

    return ctor.Invoke(injectionServices);
}

}

编辑:这是我的场景。我重构了一些实现此接口(interface)的遗留代码。

public interface IEventDispatcher
{
    void RegisterHandler(Type handler);
    void Dispatch(DomainEvent @event);
}

在 Dispatch 方法实现中,我创建处理程序的实例:

public class InMemoryBus : IEventDispatcher
{
    private readonly List<Type> _handlers = new List<Type>();
    private readonly Func<Type, object> activator;

    /// <param name="activator">Used to create instance of message handlers</param>
    public InMemoryBus(Func<Type, object> activator)
    {
        this.activator = activator;
    }

    public void Dispatch(DomainEvent @event)
    {
        Type messageType = message.GetType();
        var openInterface = typeof(IHandleMessages<>);
        var closedInterface = openInterface.MakeGenericType(messageType);

        var handlersToNotify = from h in _handlers
                               where closedInterface.GetTypeInfo().IsAssignableFrom(h.GetTypeInfo())
                               select h;
        foreach (Type h in _handlersToNotify)
        {
            //this is the tricky part
            var handlerInstance = activator(h);
            closedInterface.GetTypeInfo()
                .GetMethod(nameof(IHandleMessages<T>.Handle))
                .Invoke(handlerInstance, new[] { message });
        }
    }

    public void RegisterHandler(Type type) => _handlers.Add(type);
}

最佳答案

https://stackoverflow.com/a/45756192/45091是正确的做事方式。

For example, how does ASP.NET Core creates controller instances?

如果您不想注册服务,您可以使用我们所说的“类型激活”。有一种名为 ActivatorUtilities 的类型,它具有您想要的帮助器方法。您调用 ActivatorUtilities.CreateInstance(serviceProvider, type) ,它将使用指定的服务提供程序激活该类型。

关于c# - 使用ctor注入(inject)和ServiceProvider创建实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45755871/

相关文章:

c# - 如何在 .NET Core RC2 控制台应用程序(Linux、Debian 8)中使用 System.Data?

c# - 如何在vbscript中将对象作为方法参数传递

c# - GPIO windows IOT Core 的可变电压

c# - 为什么任务在执行下一个代码之前等待Task.Run而不是Task.Factory.StartNew?

php - 克隆依赖项的副本(依赖注入(inject))是否有意义?

c# - 使用 Unity 设置依赖注入(inject)以将类的实例传递给构造函数

java - 使用 Guice 绑定(bind)服务

c# - 检测是否从已发布的独立可执行文件运行

c# - 如何结束字符串中的代码?

.net - 丢失版本和工具 : . NET Core、Core Tools、dotnet Core CLI,