ASP.NET core:需要显式访问 ServiceCollection?

com*_*e73 5 .net c# .net-core

我了解如何注册 ASP.NET core 的依赖项以及构造函数注入如何为我的控制器工作(我已经可以工作了)。是否所有内容都必须通过构造函数传递,然后显式传递到由这些构造对象创建的对象,或者实例化的对象(例如我的控制器)以及它们创建的对象如何使用服务集合来访问或实例化其他对象物体?

2020 年 6 月 19 日更新:

假设我的 Startup 调用了这个(这只是示例代码,看看我是否能得到这个问题,从而使我的帐户被取消):

    public static IServiceCollection AddRepository(
        this IServiceCollection services,
        IConfiguration configuration)
    {
        var serviceProvider = services.BuildServiceProvider(); //TODO: dispose
        ContentstackClient stack = serviceProvider.GetService<ContentstackClient>();
        Trace.Assert(stack != null, "configure ContentstackClient service before IRepository service");
        IConfigureSerialization configurator = serviceProvider.GetService<IConfigureSerialization>();
        Trace.Assert(configurator != null, "configure IConfigureSerialization before ContentstackRepository");
        configurator.ConfigureSerialization(stack.SerializerSettings);
        //TODO: Apply ContentstackRepositoryConfiguration (UseSync, etc.) from appsettings.json
        ContentstackRepositoryConfiguration repoConfig = ContentstackRepositoryConfiguration.Get(
            ContentstackRepositoryConfiguration.StartType.FastestStartSync, stack);
            services.AddSingleton<IRepository>(new ContentstackRepository(repoConfig));//, serviceProvider.GetService<ILogger>()));
//TODO: happens automatically?            serviceProvider.Dispose();
            return services;
        }
Run Code Online (Sandbox Code Playgroud)

我的控制器中有这个:

    public EntryController(
        IRepository repository, 
        ILogger<EntryController> logger, 
        ContentstackClient stack)
    {
        _repository = repository;
        _logger = logger;
        _stack = stack;
    }
Run Code Online (Sandbox Code Playgroud)

但是,如果我的视图或其他地方的代码想要访问 IRepository 单例怎么办?我是否必须到处传递 IRepository,或者是否有某种方法可以通过服务定位器或其他方式显式访问它?

Cha*_*nds 3

我知道asp.net core DI框架支持三种类型的组件注入。
(1) Constructor
(2) Paramter invocation
(3) HttpContext.RequestServices

Note: HttpContext.RequestServices makes use of the service locator pattern. It's not a good pattern but if you lost access to the service and you can only get it through HttpContext.RequestServices, then it may be acceptable.
Here is a discussion about it.

I refactored your code to register a Repository service.

public static IServiceCollection AddRepository(
    this IServiceCollection services,
    IConfiguration configuration)
{
    // You can declare a singeton instance then declare IRepository is service and ContentstackRepository is your implementation class
    // When you use pass IRepository in the controller constructor, actually you get the ContentstackRepository instance.
    services.AddSingleton<IRepository, ContentstackRepository>(f => 
    {
        // Don't use this approach in the IServiceCollection, if you want register the instance.        
        // var serviceProvider = services.BuildServiceProvider();
    
        // You can use the 'f' lamda to get IServiceProvider and use GetService to get the instance.
        ContentstackClient stack = f.GetService<ContentstackClient>();
        Trace.Assert(stack != null, "configure ContentstackClient service before IRepository service");
    
        IConfigureSerialization configurator = f.GetService<IConfigureSerialization>();
        Trace.Assert(configurator != null, "configure IConfigureSerialization before ContentstackRepository");        
        configurator.ConfigureSerialization(stack.SerializerSettings);
    
        // return ContentstackRepository instance 
        ContentstackRepositoryConfiguration repoConfig = ContentstackRepositoryConfiguration.Get(ContentstackRepositoryConfiguration.StartType.FastestStartSync, stack);
        return new ContentstackRepository(repoConfig);  
    }); 
}   
Run Code Online (Sandbox Code Playgroud)

如果你想IRepository在另一个类中使用单例,你需要将它传递给构造函数。

如果你想使用方法或属性注入,你可以考虑使用 Autofac,它是有用的注入库。