C# ASP.NET核心:需要显式访问ServiceCollection吗?

C# ASP.NET核心:需要显式访问ServiceCollection吗?,c#,.net,.net-core,C#,.net,.net Core,我了解如何为ASP.NET core注册依赖项,以及构造函数注入如何为我的控制器工作(我有这个功能)。是否所有内容都必须通过构造函数传递,然后显式传递到由这些构造对象创建的对象,或者实例化的对象(例如我的控制器)及其创建的对象如何使用服务集合访问或实例化其他对象 更新日期:2020年6月19日: 假设我的初创公司调用了这个(这只是示例代码,看看我是否可以得到这个问题,从而取消我的帐户): 公共静态IServiceCollection AddRepository( 这是电子收款服务, i配置(配置

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

更新日期:2020年6月19日:

假设我的初创公司调用了这个(这只是示例代码,看看我是否可以得到这个问题,从而取消我的帐户):

公共静态IServiceCollection AddRepository(
这是电子收款服务,
i配置(配置)
{
var serviceProvider=services.BuildServiceProvider();//TODO:dispose
ContentstackClient stack=serviceProvider.GetService();
Assert(stack!=null,“在IRepository服务之前配置ContentstackClient服务”);
IConfigureSerialization configurator=serviceProvider.GetService();
Assert(configurator!=null,“在ContentstackRepository之前配置IConfigureSerialization”);
configurator.ConfigureSerialization(堆栈序列化设置);
//TODO:从appsettings.json应用ContentstackRepositoryConfiguration(UseSync等)
ContentstackRepositoryConfiguration repoConfig=ContentstackRepositoryConfiguration.Get(
ContentstackRepositoryConfiguration.StartType.FastTestStartSync,堆栈);
services.AddSingleton(新ContentstackRepository(repoConfig));/,serviceProvider.GetService());
//TODO:自动发生?serviceProvider.Dispose();
返回服务;
}
我的控制器中有:

    public EntryController(
        IRepository repository, 
        ILogger<EntryController> logger, 
        ContentstackClient stack)
    {
        _repository = repository;
        _logger = logger;
        _stack = stack;
    }
公共入口控制器(
i存储库,
ILogger记录器,
ContentstackClient(客户端堆栈)
{
_存储库=存储库;
_记录器=记录器;
_堆栈=堆栈;
}

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

我认为您有两种选择:

  • 您可以尝试在Startup类中使用方法注册IRepository的实现

  • 我知道asp.net核心di支持三组件注入。
    (1) 构造函数
    (2)
    (3) HttpContext.RequestServices

    注意:HttpContext.RequestServices是一种服务定位器模式。这不是一个好的模式,但是如果您在某些情况下丢失了服务,并且在这种情况下可以获得HttpContext.RequestServices,那么您可以使用它。
    下面是一个关于HttpContext.RequestServices的示例

    我将重构您的代码以注册存储库,并提示一些提示将对您有所帮助

    public static IServiceCollection AddRepository(
        this IServiceCollection services,
        IConfiguration configuration)
    {
        // You can declare 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);  
        }); 
    }   
    
    公共静态IServiceCollection AddRepository(
    这是电子收款服务,
    i配置(配置)
    {
    //您可以声明Singleton实例,然后声明IRepository是服务,ContentstackRepository是您的实现类
    //当您在控制器构造函数中使用pass-IRepository时,实际上您得到了ContentstackRepository实例。
    services.AddSingleton(f=>
    {
    //如果要注册实例,请不要在IServiceCollection中使用此方法。
    //var serviceProvider=services.BuildServiceProvider();
    //您可以使用“f”lamda获取IServiceProvider,并使用GetService获取实例。
    ContentstackClient stack=f.GetService();
    Assert(stack!=null,“在IRepository服务之前配置ContentstackClient服务”);
    IConfigureSerialization configurator=f.GetService();
    Assert(configurator!=null,“在ContentstackRepository之前配置IConfigureSerialization”);
    configurator.ConfigureSerialization(堆栈序列化设置);
    //返回ContentstackRepository实例
    ContentstackRepositoryConfiguration repoConfig=ContentstackRepositoryConfiguration.Get(ContentstackRepositoryConfiguration.StartType.FastestStartSync,stack);
    返回新的ContentstackRepository(repoConfig);
    }); 
    }   
    
    如果要在其他类中使用IRepository单例,则需要在其他构造函数中传递IRepository。


    如果您想使用方法注入和属性注入,我认为您可以考虑这是有用的DI注入库。

    < p>您至少有四个选项可以使用.NET内核中的依赖性注入:

    构造函数注入:这是框架中的一些魔法。我不知道它是如何工作的,但至少当您没有显式地实例化对象时,它是如何工作的。控制器就是一个很好的例子。您所需要做的就是在控制器中实现构造函数,以接受框架从服务提供者实例化的参数。您可以将它们存储在控制器对象中,然后将它们传递给调用堆栈中更深的任何对象。确保在框架实例化控制器之前注册了所有必需的服务

    第三方依赖注入框架:有很多具有各种特性和性能配置文件的框架,对我来说,所有这些框架都超出了范围,因为它们不是框架本身固有的,我不想把我的观点强加给任何使用我的代码的人。提到任何,我几乎肯定会排除一些,因为我不打算使用它们,所以我不会列出任何。其中哪一个能在即将到来的DI战争中幸存下来?谁知道呢。我想使用.NET本身,而不是第三方扩展

    反射:您可以使用反射来检查一个或多个程序集中的类型,以查找满足约定或定义了属性的类型。我认为这是隐含的一种形式。
    services.AddSingleton<IRepository, [class_that_implements_IRepository]>();
    
        public interface IRepository
        {
            int DoSomething();
        }
    
        public class MyRepositoryImplementation : IRepository
        {
            public int DoSomething()
            {
                return 42;
            }
        }
    
        public static class MyRepositorySingleton
        {
            private static IRepository _repository = null;
    
            static MyRepositorySingleton()
            {
                _repository = new MyRepositoryImplementation();
            }
    
            public static IRepository GetRepository()
            {
                return _repository;
            }
        }
    
    
    public static IServiceCollection AddRepository(
        this IServiceCollection services,
        IConfiguration configuration)
    {
        // You can declare 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);  
        }); 
    }