【问题标题】:DI not injecting service to ControllerDI 不向控制器注入服务
【发布时间】:2019-06-23 15:20:31
【问题描述】:

我有一个奇怪的情况。我在启动类中注册了我的服务,就像这样

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddSingleton<ISearchService, SearchService>();
    services.AddSingleton<IBrandSearchService, BrandSearchService>();
    services.AddSingleton<INearbySearchService, NearbySearchService>();
    services.AddSingleton<ILocationService, LocationService>();
    ...
}

但是当我尝试在控制器的构造函数中访问它们时,它们为空,即使我将它添加到构造函数参数中,或者尝试从 ServiceCollection 中获取

public class SuggestController
{
    readonly ILocationService locationService;

    public SuggestController(IOptions<SiteSettings> settings, IOptions<DBAccessBuilder> access, IStringLocalizer<SharedResources> localizer, IMemoryCache memoryCache, IHostingEnvironment environment)
    {
        this.locationService = (ILocationService)new ServiceCollection().BuildServiceProvider().GetService(typeof(ILocationService));
    }
}

实现 ILocationService 接口的 My Location 类

public class LocationService : ILocationService
{
    readonly ISolrOperations<LocationResult> search;

    ...

    public LocationService(ISolrOperations<LocationResult> search)
    {
        this.search = search;
    }

    ...
}

我错过了什么?

【问题讨论】:

  • 你正在创建一个全新的ServiceCollection 实例,它是empty,然后用它来尝试获取一个已经用不同 IServiceCollection。为什么不直接将ILocationService 参数带入SuggestController 构造函数?
  • 我以前就是这么做的。如果这样做,我会得到 InvalidOperationException: Unable to resolve service for type 'SolrNet.ISolrOperations`1[LocationResult]' 同时尝试激活 'LocationService'。
  • 那只是因为你还没有在 DI 注册ISolrOperations&lt;LocationResult&gt;
  • @KirkLarkin 可能是他没有赶上事情。如果您将其作为完整答案发布,那就太好了。

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


【解决方案1】:

您没有注入您的服务。相反,您尝试使用服务定位器反模式来获取它,但您实际上并没有使用真正的服务集合。您正在创建一个新的服务集合,但没有注册您想要的服务,并试图从中提取您的服务,这当然会失败。

尽管这不是正确的方法,但要真正正确使用服务定位器反模式,您需要注入 IServiceProvider

public SuggestController(IServiceProvider provider, ...)
{
    this.locationService = provider.GetRequiredService<ILocationService>();
}

那么,这只会起作用,因为在这种情况下,您的特定服务是单例的。如果是作用域,则必须先创建作用域:

using (var scope = provider.CreateScope())
{
    var locationService = scope.ServiceProvider.GetRequiredService<ILocationService>();
}

但是,在某个范围内检索到的任何内容都只能在该范围内使用。因此,对于作用域服务,您必须将每个操作都包装在这样的 using 中(即,您不能将服务持久化到 ivar)。

所有这些,在这里,您正在注入控制器,因此,您可以直接注入您的依赖项,而不必依赖服务定位器反模式(这是一个反模式是有原因的)。所以你真正需要做的只是注入ILocationService

public SuggestController(ILocationService locationService, ...)
{
    this.locationService = locationService;
}

【讨论】:

    猜你喜欢
    • 2016-04-09
    • 1970-01-01
    • 2015-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-23
    • 2017-01-21
    • 2016-01-28
    相关资源
    最近更新 更多