【问题标题】:How to create instance of a class and inject services?如何创建类的实例并注入服务?
【发布时间】:2016-01-18 14:03:03
【问题描述】:

新的 aspnet 具有内置依赖注入:启动类实例接收服务、控制器、视图组件。有什么方法可以让我创建我的类的对象并使用 aspnet 功能传递服务?比如:

WebApplicationClassesActivator.Create(typeof(MyClass))

例如,MyClass 包含接收IHostingEnvironment 实例的构造函数。

实际用法:

public class MyController : Controller
{
    private readonly IContext Context;
    public MyController(IContext context)
    {
        Context = context;
    }
    public IActionResult Index(string className)
    {            
        return View(WebApplicationClassesActivator.Create(Type.GetType(className)));
    }
}

classsName 是类的名称,例如:

public class A
{
    public A(IContext context, IHostingEnvironment env)
    {
       ...
    }
}

【问题讨论】:

  • 您能详细说明一下吗?现在还不太清楚 - 你想做什么。您是否尝试使用 ASP.NET 内置 DI 容器将某些接口绑定到实现?然后看services.AddTransient等等。
  • 是的,我在 Startup 和控制器操作中添加了一些瞬态、一个作用域和一个单例,我创建了另一个我的类的实例并希望传递一些服务(标准并且我也添加了)跨度>
  • 目前还不太清楚你的问题是什么。你能用代码示例说明一下吗?
  • 好吧,从我的角度来看,您的场景与 DI 无关,因为它只是按类型名称创建实例(但是它稍微看起来像应用程序中的服务位置例如,使用构造函数注入代码而不是真正的依赖注入 - 因此看起来像一个反模式)。在您的特定情况下,为什么不只是Activator.CreateInstance(Type.GetType(className))?我错过了什么吗?
  • @AndyKorneyev 只是因为className-class 有需要IContextIHostingEnvironment 等实现实例传入的构造函数。

标签: c# asp.net-mvc dnx


【解决方案1】:

Assembly Microsoft.Extensions.DependencyInjection.Abstractions 包含静态类 ActivatorUtilities,它有我需要的东西:

public static object CreateInstance(IServiceProvider provider, 
                                    Type instanceType, 
                                    params object[] parameters);

我可以创建实例并注入服务:

private readonly IServiceProvider Provider;

public HomeController(IServiceProvider provider)
{       
    Provider = provider;
}

public IActionResult Index()
{       
    var instance = ActivatorUtilities.CreateInstance(Provider, typeof(A));

    return View(instance);
}

public class A
{
    public A(IContext context)
    {

    }
}

【讨论】:

  • 这在 .net40 中可用吗?
【解决方案2】:

好吧,您可以通过以下方式进行:

public class MyController : Controller
{
    private readonly IContext Context;
    private readonly IServiceProvider _Provider;

    public MyController(IContext context, IServiceProvider provider)
    {
        Context = context;
        _Provider = provider;
    }

    public IActionResult Index(string className)
    {            
        return View(_Provider.GetService(Type.GetType(className)));
    }
}

当然,您计划以这种方式实例化的每个类都应该添加到 ConfigureServices 中,例如:

services.AddTransient<MyClass, MyClass>();

另请注意 - 这个实现实际上是服务定位器,通常被认为是设计反模式。

【讨论】:

  • 我不认为,例如,每个 Controller 类后代都会被添加到服务中以允许创建它。
  • 嗯?你在说什么控制器后代?关于实例化的短语是关于动作方法的“className”参数 - 应将具有这样名称的类添加到服务中,以便 DI 容器能够解析它。如果它不适合您 - 那么您可能应该使用另一个 DI 容器,而不是内置容器。
  • 但是您的尝试仍然需要将 A 类添加到服务中,以便服务提供者能够解决它。还是我还缺少什么?
  • 不,不是。 DI 中的服务用于作为构造函数参数,这就是为什么它们存储在 DI 引擎中的某个位置。因此,这些服务中需要的其他对象将仅在创建步骤时与 DI 交互。
  • 嗯.. 看起来这是我对 vNext DI 知识的一个空白。 ;)
猜你喜欢
  • 1970-01-01
  • 2016-11-09
  • 1970-01-01
  • 2021-10-04
  • 2014-08-28
  • 1970-01-01
  • 2021-02-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多