使用ctor注入和ServiceProvider创建实例

Lie*_*ero 0 c# dependency-injection inversion-of-control .net-core

我知道有IServiceCollection接口可以注册我的服务,IServiceProvider并且可以实例化服务.

如何基于使用已注册服务的指定Type实例化一个类?

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

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

MyClass instance = CreateInstance(typeof(MyClass));

object CreateIntance(Type type)
{
   ???
}
Run Code Online (Sandbox Code Playgroud)

例如,ASP.NET Core如何创建控制器实例?

我已经初步实现了激活器,但是在.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);
}
Run Code Online (Sandbox Code Playgroud)

}

编辑:这是我的情景.我重构了一些实现此接口的遗留代码.

public interface IEventDispatcher
{
    void RegisterHandler(Type handler);
    void Dispatch(DomainEvent @event);
}
Run Code Online (Sandbox Code Playgroud)

在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);
}
Run Code Online (Sandbox Code Playgroud)

dav*_*owl 14

/sf/answers/3202933471/是正确的做事方式。

例如,ASP.NET Core 如何创建控制器实例?

如果您不想注册服务,您可以使用我们所说的“类型激活”。有一种称为 ActivatorUtilities 的类型,它具有您想要的辅助方法。您拨打电话ActivatorUtilities.CreateInstance(serviceProvider, type),它将通过指定的服务提供商激活该类型。


Nko*_*osi 7

特定

public class MyClass {
    public MyClass(ISomeService someService) { 
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)

您需要构建整个对象图,以便提供者知道它可以创建什么

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

IServiceProvider provider = serviceCollection.BuildServiceProvider();

MyClass instance = provider.GetService<MyClass>();
Run Code Online (Sandbox Code Playgroud)

provider.GetService<MyClass>()被称为提供商将初始化MyCLass,解决过程中的所有依赖关系.

ASP.NET核心中依赖注入的参考介绍