Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/324.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# 如何从c Core中的DI获取可用的IOption列表?_C#_Dependency Injection_.net Core - Fatal编程技术网

C# 如何从c Core中的DI获取可用的IOption列表?

C# 如何从c Core中的DI获取可用的IOption列表?,c#,dependency-injection,.net-core,C#,Dependency Injection,.net Core,在这篇文章之后: 我现在可以在服务需要时验证设置。我想做的是在program.cs中直接验证服务器何时启动 我不知道怎么做?是否有办法获取DI中注入的服务列表,然后验证该类型是否可从IOption分配并注册 以下是我如何向DI添加设置: //App settings services.ConfigureAndValidate<AuthenticationSettings>(Configuration); services.ConfigureAndValidat

在这篇文章之后:

我现在可以在服务需要时验证设置。我想做的是在program.cs中直接验证服务器何时启动

我不知道怎么做?是否有办法获取DI中注入的服务列表,然后验证该类型是否可从IOption分配并注册

以下是我如何向DI添加设置:

    //App settings
    services.ConfigureAndValidate<AuthenticationSettings>(Configuration);
    services.ConfigureAndValidate<SmtpSettings>(Configuration);
我更新Program.cs,比如:

using Autofac;
using Autofac.Core;



var options = services.GetService<ILifetimeScope>()
   .ComponentRegistry
   .Registrations.SelectMany(e => e.Services)
   .Select(s => s as TypedService)
   .Where(s => s.ServiceType.IsGenericType && s.ServiceType.GetGenericTypeDefinition() == typeof(IConfigureOptions<>))
   .Select(s => s.ServiceType.GetGenericArguments()[0])
   .Where(s => typeof(ISettings).IsAssignableFrom(s))
   .ToList();

所以现在我需要实例化options中的每个选项并获得值。我还在努力。如果您有任何建议或解决方案,请告诉我:

您可以通过迭代IServiceCollection实例获得已配置选项类型的列表:

var configuredOptionTypes =
    from descriptor in services
    let serviceType = descriptor.ServiceType
    where serviceType.IsGenericType
    where serviceType.GetGenericTypeDefinition() == typeof(IConfigureNamedOptions<>)
    let optionType = serviceType.GetGenericArguments()[0]
    select optionType;

根据Steven的建议,以下是我的解决方案: 我的设置验证程序服务

    public SettingsValidator(
        IServiceProvider services,
        ILifetimeScope scope
    )
    {
        var types = scope.ComponentRegistry.Registrations
            .SelectMany(e => e.Services)
            .Select(s => s as TypedService)
            .Where(s => s.ServiceType.IsAssignableToGenericType(typeof(IConfigureOptions<>)))
            .Select(s => s.ServiceType.GetGenericArguments()[0])
            .Where(s => typeof(ISettings).IsAssignableFrom(s))
            .ToList();

        foreach (var t in types)
        {
            var option = services.GetService(typeof(IOptions<>).MakeGenericType(new Type[] { t }));
            option.GetPropertyValue("Value");
        }
    }
扩展

public static class TypeExtensions
{
    public static bool IsAssignableToGenericType(this Type givenType, Type genericType)
    {
        foreach (var it in givenType.GetInterfaces())
        {
            if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType)
                return true;
        }

        if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
            return true;

        Type baseType = givenType.BaseType;
        if (baseType == null) return false;

        return IsAssignableToGenericType(baseType, genericType);
    }
}
在program.cs中

using (var scope = webHost.Services.CreateScope())
        {
            var services = scope.ServiceProvider;
            var logger = services.GetRequiredService<ILogger<Program>>();
            try
            {
                logger.LogInformation("Starting settings validation.");
                services.GetRequiredService<SettingsValidator>();
                logger.LogInformation("The settings have been validated.");
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "An error occurred while validating the settings.");
            }
        }

让我知道它是否也适用于您:

嗨,谢谢您的回答。在Program.cs中,我还没有IServiceCollection,我试图从services.GetRequiredService获取它,但它不起作用。我如何获得它?除非您显式地将IServiceCollection存储在某个位置,否则它将在使用该集合构建ServiceProvider后消失。但是你还不可能像以前那样拥有这个系列。这是您调用AddTransient和AddSingleton的对象。我找到了一种使用Autofac的方法,我将很快更新我的问题,但我仍然没有找到完整的答案,它已关闭:此集合在Startup类中可用。我更新了我的答案,现在我可以获得设置类型的列表。您知道如何执行以下操作吗:services.getServiceIOOptions
    public SettingsValidator(
        IServiceProvider services,
        ILifetimeScope scope
    )
    {
        var types = scope.ComponentRegistry.Registrations
            .SelectMany(e => e.Services)
            .Select(s => s as TypedService)
            .Where(s => s.ServiceType.IsAssignableToGenericType(typeof(IConfigureOptions<>)))
            .Select(s => s.ServiceType.GetGenericArguments()[0])
            .Where(s => typeof(ISettings).IsAssignableFrom(s))
            .ToList();

        foreach (var t in types)
        {
            var option = services.GetService(typeof(IOptions<>).MakeGenericType(new Type[] { t }));
            option.GetPropertyValue("Value");
        }
    }
        builder.RegisterType<SettingsValidator>();
public class AzureStorageSettings : ISettings
{
    [Required]
    public string ConnectionString { get; set; }
    [Required]
    public string Container { get; set; }
    [Required]
    public string Path { get; set; }
}
public static class TypeExtensions
{
    public static bool IsAssignableToGenericType(this Type givenType, Type genericType)
    {
        foreach (var it in givenType.GetInterfaces())
        {
            if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType)
                return true;
        }

        if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
            return true;

        Type baseType = givenType.BaseType;
        if (baseType == null) return false;

        return IsAssignableToGenericType(baseType, genericType);
    }
}
using (var scope = webHost.Services.CreateScope())
        {
            var services = scope.ServiceProvider;
            var logger = services.GetRequiredService<ILogger<Program>>();
            try
            {
                logger.LogInformation("Starting settings validation.");
                services.GetRequiredService<SettingsValidator>();
                logger.LogInformation("The settings have been validated.");
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "An error occurred while validating the settings.");
            }
        }