Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .Net核心依赖项注入:获取servicetype(接口)的实现类型_C#_.net Core_Dependency Injection - Fatal编程技术网

C# .Net核心依赖项注入:获取servicetype(接口)的实现类型

C# .Net核心依赖项注入:获取servicetype(接口)的实现类型,c#,.net-core,dependency-injection,C#,.net Core,Dependency Injection,是否可以获取servicetype的已注册实现的类型 例如: 在我的Startup.ConfigureServices中,我注册了这样的服务(没有什么特别的): public void配置服务(IServiceCollection服务) { //... services.AddTransient(); //... } IBaseRepository是服务类型,BaseRepository是具体实现 问题 是否有方法获取服务接口的注册类型(而不是实例)? 在我的示例中,我想请求IBaseRepo

是否可以获取servicetype的已注册实现的类型

例如: 在我的
Startup.ConfigureServices
中,我注册了这样的服务(没有什么特别的):

public void配置服务(IServiceCollection服务)
{
//...
services.AddTransient();
//...
}
IBaseRepository
是服务类型,
BaseRepository
是具体实现

问题

是否有方法获取服务接口的注册类型(而不是实例)? 在我的示例中,我想请求
IBaseRepository
并获取类型
BaseRepository

于2021年2月10日13:13 UTC编辑:以下信息不是问题的一部分,具有误导性。 我的问题的更多背景信息

稍后,我需要这个服务的一个实例,并希望使用 ,因为我需要在构造函数中传递值,该值只有在运行时才知道。 在这里,我需要为我想要获得新实例的类传递具体类型。
如果我可以将接口类型传递到我的方法中,确定为该接口注册了哪个类并创建一个新实例,那就太好了。

对于您的场景,您实际上不需要使用ActivatorUtilities:

从about
GetRequiredService
查看此代码,因为我认为它将解决您的问题

    public static void Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();

        using (var serviceScope = host.Services.CreateScope())
        {
            var services = serviceScope.ServiceProvider;

            try
            {
                var myDependency = services.GetRequiredService<IMyDependency>();
                myDependency.WriteMessage("Call services from main");
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred.");
            }
        }

        host.Run();
    }
publicstaticvoidmain(字符串[]args)
{
var host=CreateHostBuilder(args.Build();
使用(var serviceScope=host.Services.CreateScope())
{
var services=serviceScope.ServiceProvider;
尝试
{
var myDependency=services.GetRequiredService();
myDependency.WriteMessage(“主叫服务”);
}
捕获(例外情况除外)
{
var logger=services.GetRequiredService();
LogError(例如,“发生错误”);
}
}
host.Run();
}
为什么这是首选:

  • 您没有在DI容器之外的任何地方添加实例化逻辑,因此没有副作用
  • 在您的例子中,您添加了一个
    瞬态
    作用域服务,因此它应该是正常的。如果这是一个单例,那么由activator创建一个新的单例将是一个糟糕的做法,因为您将违反原始作者的意图,并产生未知的副作用(好的,它们可能是已知的,但您明白我的意思)

  • 现在还不完全清楚你为什么需要这个,但是。。。
    IServiceCollection
    (不是内置的
    IServiceProvider
    )只是对象的集合。用于配置DI的所有扩展方法本质上都是向集合添加一个或多个描述符

    因为它实现了
    IList
    (因此
    IEnumerable
    ),所以您可以对它执行LINQ操作以查找特定的描述符。
    ServiceDescriptor
    上有四个值得注意的属性,它们描述服务及其实现

    • 服务类型
      -必需;将从DI请求的
      类型
      。通常但不总是一个接口
    • 实现类型
      -可选;已注册的混凝土
      类型
    • 实现实例
      -可选;单例实例(静态类型
      对象
    • 实现工厂
      -可选;用作工厂方法的
      Func
    在三个可选属性中,将/必须指定一个(并且只有一个)。第五个属性
    Lifetime
    描述了生存期(单例、作用域、瞬态)

    如果要查找与特定服务类型关联的具体类型s,可以使用以下扩展方法:

    公共静态IEnumerable GetImplementationTypes(此IServiceCollection服务)
    where-TService:class
    {
    if(服务为空)
    抛出新的ArgumentNullException(nameof(services));
    回程服务
    。其中(d=>d.ServiceType==typeof(TService)&&d.ImplementationType!=null)
    .选择(d=>d.ImplementationType);
    }
    //或者
    公共静态IEnumerable GetImplementationTypes(此IServiceCollection服务,类型serviceType)
    {
    if(服务为空)
    抛出新的ArgumentNullException(nameof(services));
    if(serviceType为null)
    抛出新ArgumentNullException(nameof(serviceType));
    回程服务
    .Where(d=>d.ServiceType==ServiceType&&d.ImplementationType!=null)
    .选择(d=>d.ImplementationType);
    }
    
    然后您可以使用:

    IServiceCollection服务=。。。
    var typeList=services.GetImplementationTypes().ToList();
    

    请注意,这将返回一个
    IEnumerable
    ,因为您可以对单个服务类型进行多个注册。它还将只返回那些已注册类型的,而不返回那些使用工厂或单实例的。

    嗨,Athanasios,谢谢你的回答。但是
    GetRequiredService
    如何帮助将参数传递给服务的构造函数,而该构造函数未在DI容器中注册?您将传递参数并在类中使用GetRequiredService。或者是我误解了什么?对不起,我知道我的问题不清楚。毫无疑问,如何使用
    ActivatorUtilities.CreateInstance
    。问题是如何获取为servicetype注册的IMementations的信息。这似乎是一个问题。根据背景,目前的问题也不完整,因此不清楚。阅读并编辑问题,以提供一个可用于重现问题的答案,从而获得更好的答案