DI不向控制器注入服务

时间:2019-01-30 10:59:49

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

我有一个奇怪的情况。我像这样

在启动类中注册我的服务
public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddSingleton<ISearchService, SearchService>();
    services.AddSingleton<IBrandSearchService, BrandSearchService>();
    services.AddSingleton<INearbySearchService, NearbySearchService>();
    services.AddSingleton<ILocationService, LocationService>();
    ...
}

但是当我尝试在控制器的构造函数中访问它们时,它们为null,即使我将其添加到构造函数参数中,或尝试从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接口的我的Location类

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

    ...

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

    ...
}

我想念什么?

1 个答案:

答案 0 :(得分:0)

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

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

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

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

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

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

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

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