【问题标题】:Instantiating objects with .NET Core's DI container使用 .NET Core DI 容器实例化对象
【发布时间】:2017-03-13 01:49:21
【问题描述】:

我正在使用IServiceCollection 为我的对象创建所需服务的列表。现在我想实例化一个对象并让 DI 容器解析该对象的依赖关系

示例

// In my services config.
services
    .AddTransient<IMyService, MyServiceImpl>();

// the object I want to create.
class SomeObject
{
    public SomeObject(IMyService service)
    {
        ...
    }
}

如何让 DI 容器创建 SomeObject 类型的对象,并注入依赖项? (大概这就是它对控制器的作用?)

注意:我不想将SomeObject 存储在服务集合中,我只想能够做这样的事情......

SomeObject obj = startup.ServiceProvider.Resolve<SomeObject>();

... 基本原理:我不必将所有控制器都添加到服务容器中,所以我不明白为什么还要向它添加 SomeObject!?

【问题讨论】:

  • 您想在哪里/如何创建对象?
  • @Nkosi 在控制台应用程序的 Main 方法中......类似于 SomeObject x = startup.ServiceProvider.ResolveDependenciesFor();
  • Rationale: I don't have to add all of my controllers to the service container, so I don't see why I would have to add SomeObject to it either 框架正在为你做这件事。它使用约定并为您注册所有控制器

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


【解决方案1】:

如标记答案的 cmets 中所述,您可以使用 ActivatorUtilities.CreateInstance 方法。这个功能已经存在于 .NET Core 中(我相信从 1.0 版开始)。

见:https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.activatorutilities.createinstance

【讨论】:

    【解决方案2】:

    这有点粗糙,但是这行得通

    public static class ServiceProviderExtensions
        {
            public static TResult CreateInstance<TResult>(this IServiceProvider provider) where TResult : class
            {
                ConstructorInfo constructor = typeof(TResult).GetConstructors()[0];
    
                if(constructor != null)
                {
                    object[] args = constructor
                        .GetParameters()
                        .Select(o => o.ParameterType)
                        .Select(o => provider.GetService(o))
                        .ToArray();
    
                    return Activator.CreateInstance(typeof(TResult), args) as TResult;
                }
    
                return null;
            }
        }
    

    【讨论】:

    • 如何使用IServiceProvider 实例化对象(注入所有依赖项)?
    • @alexw .Select(o => provider.GetService(o))
    • @alexw 基本原理,只要有一个构造函数,迭代它的参数类型,使用服务提供者解析它们,然后使用结果创建一个实例。
    • @flodin 我已经很久没有写这个了,但是是的,我认为这个功能已经存在。嵌入 .NET Core 的 DI 东西实现了服务定位器模式。这应该会引导您朝着正确的方向前进...joonasw.net/view/aspnet-core-di-deep-dive
    • ok 但在 .NET Core 中,他们说的是: var instance = (IPipe)ActivatorUtilities.CreateInstance(serviceProvider, pipeType); .但是你仍然需要一个 ServiceProvider 对象:-(。我不明白为什么他们很难在一个自写的类中用 DI 实例化一个类。
    【解决方案3】:

    扩展方法:

    public static class Extensions
    {
        public static T BuildObject<T>(this IServiceProvider serviceProvider, params object[] parameters)
            => ActivatorUtilities.CreateInstance<T>(serviceProvider, parameters);
    }
    

    用法:

    [HttpGet]
    public IEnumerable<WeatherForecast> Get()
    {
        var ss = HttpContext.RequestServices.BuildObject<SomeService>();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-24
      • 2019-02-16
      • 1970-01-01
      • 1970-01-01
      • 2020-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多