【问题标题】:Can't inject a delegate using ASP.NET Core DI无法使用 ASP.NET Core DI 注入委托
【发布时间】:2017-12-27 09:22:45
【问题描述】:

假设我有一个这样的 MVC 核心控制器:

public class SomeController
{
     public SomeController(IConfiguration appConfig, Func<string> someDelegate)
     {
     }
}

另外,我正在使用 AutoFac 来解决注入。对象注入工作完美,而添加委托注入会产生一个 ASP.NET Core 异常,该异常告诉 Func&lt;string&gt; 无法注入,因为没有可以注入此类类型的组件。

当我尝试使用 AutoFac 手动解析 SomeController 时,我得到了所需的行为。

有什么方法可以在不使用 AutoFac 解析控制器的情况下支持这种情况?

【问题讨论】:

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


    【解决方案1】:

    控制器默认不通过DI解析,它们是在DefaultControllerFactory左右构造的。

    更新

    Microsoft.Extensions.DependencyInjection 不支持命名组件、发现、自动注册、装饰器等。

    它旨在简化开箱即用的 IoC,并为基本应用程序的 DI 提供基础,并为集成 3rd 方 IoC 容器(具有自动发现、装饰器等高级功能)提供简单的方法(基本上所有他们需要处理IServiceCollection 中的信息,并从Configure 方法返回他们自己的IServiceProvider 实现。

    标签助手、控制器和视图组件在这方面是不同的,因为它们有自己的激活器(默认使用激活实用程序,在管道的某个时候使用服务提供者)。由于这个原因,AddControllersAsServices 存在,因为它用ServiceBasedActivator(使用IServiceProvider,请参阅ServiceBasedControllerActivator)替换了DefaultControllerActivator(使用ActivationUtilities,请参阅DefaultControllerActivator.cs)。

    另请参阅this related answer,了解有关如何通过 DI 解析控制器、标签助手和查看组件的详细信息。

    var builder = services
        .AddMvc()
        .AddControllersAsServices() // this one for your case
        .AddViewComponentsAsServices()
        .AddTagHelpersAsServices();
    

    【讨论】:

    • 感谢您的努力,但请记住,我的 Q 有这样的文字:有什么方法可以在不使用 AutoFac 解析控制器的情况下支持这种情况? 并且,除了将委托注入控制器的构造函数,您不需要AddControllersAsServices 方法。
    • 首先,我不知道您的注册情况,因此很难判断出了什么问题。可能您使用了一些NamedParameter,或者只在服务上进行了注册,但没有在 Autofac 上进行注册,反之亦然。 Func&lt;string&gt; 是一个奇怪的委托,这意味着它总是会解析一个字符串,因为它是无参数的。还有什么问题添加AddControllersAsServices()
    • 是的,它是一个命名组件。 Func&lt;string&gt; 是一个基本示例。实际情况可能是Func&lt;(string x, int y), Task&lt;Stream&gt;&gt;
    • 可能我的问答应该被标记为 dup。我在这几个小时内做了一些调查,发现其他人提出了类似的问题。
    • 嗯,Microsoft.Extensions.DependencyInjection 不支持命名组件、发现、自动注册、装饰器等。它的目的是简单并为 DI 提供基础,并轻松地为第 3 方 IoC 容器挂钩in.标签助手、控制器和视图组件在这方面是不同的,因为它们有自己的激活器(默认使用激活实用程序,在某些时候使用服务提供者)。因此存在AddControllersAsServices(它取代了@987654343 @ (ActivationUtilities) 和 ServiceBasedActivator (ServicerRovider)
    【解决方案2】:

    我自己也遇到了这个问题,所以我想我会分享以供将来参考,因为我有一个案例,我想解决一个委托,但包含一个额外的库似乎有点矫枉过正。

    给出以下定义:

    public interface ISomething { /*...*/ };
    public interface ISomeService { /*...*/ }
    
    public class SomeService : ISomeService { /*...*/ }
    
    public class Something
    {
        public Something(ISomeService service, string key) { /*...*/ }
    }
    
    // I prefer using a delegate for readability but you
    // don't have to use one
    public delegate ISomething CreateSomething(string key);
    

    委托可以这样注册:

    var builder = services
        .AddSingleton<ISomeService, SomeService>()
        .AddTrasient<CreateSomething>(provider => key => new Something(provider.GetRequiredService<ISomeService>(), key));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-22
      • 2017-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-22
      相关资源
      最近更新 更多