代码之家  ›  专栏  ›  技术社区  ›  Joshua Walsh

将配置绑定到中的对象图。NET Core 2.0

  •  12
  • Joshua Walsh  · 技术社区  · 7 年前

    我正在做一个。NET Core 2.0应用程序,我需要对其进行配置。我在看 this documentation 看起来是这样的。NET Core 1.0您可以做到:

    var appConfig = new AppSettings();
    config.GetSection("App").Bind(appConfig);
    

    和中。NET Core 1.1您可以执行以下操作:

    var appConfig = config.GetSection("App").Get<AppSettings>();
    

    但既不绑定也不获取。NET Core 2.0。实现这一目标的新方法是什么?

    谢谢

    乔希

    5 回复  |  直到 7 年前
        1
  •  15
  •   poke    7 年前

    您仍然可以同时执行这两项操作。因为您位于控制台应用程序中,因此可能不使用ASP。NET核心元包,您需要确保具有正确的依赖项。

    为了将配置绑定到对象,您需要 Microsoft.Extensions.Configuration.Binder 包裹那么,这两种解决方案应该都能很好地发挥作用。


    顺便说一句,即使您在控制台应用程序中,也可以使用ASP附带的依赖项注入容器。净核心。我个人觉得设置起来很简单,所以如果你仍然可以修改你的应用程序来使用它,那可能是值得的。设置如下所示:

    var configuration = new ConfigurationBuilder()
        .AddJsonFile("config.json", optional: false)
        .Build();
    
    var services = new ServiceCollection();
    services.AddOptions();
    
    // add your services here
    services.AddTransient<MyService>();
    services.AddTransient<Program>();
    
    // configure options
    services.Configure<AppSettings>(configuration.GetSection("App"));
    
    // build service provider
    var serviceProvider = services.BuildServiceProvider();
    
    // retrieve main application instance and run the program
    var program = serviceProvider.GetService<Program>();
    program.Run();
    

    然后,您所有注册的服务都可以像在ASP中一样接受依赖关系。净核心。为了使用您的配置,您可以注入 IOptions<AppSettings> 像往常一样打字。

        2
  •  10
  •   Joshua Walsh    7 年前

    直到今天我终于解决了这个问题,我仍然对此有意见。

    代码运行时没有问题,但所有属性仍然为null,即使在绑定之后也是如此。我是这样做的:

    public class AppSettings
    {
        public string MyProperty
    }
    

    事实证明,你必须这样做:

    public class AppSettings
    {
        public string MyProperty { get; set; }
    }
    

    只有当类具有属性而不是字段时,它才起作用。这对我来说并不清楚。

        3
  •  2
  •   JLe    7 年前

    如果要在 Startup 将此添加到 Startup.cs :

    services.Configure<AppSettings>(Configuration.GetSection("App"));
    

    然后可以通过注入 IOptions<> :

    private readonly AppSettings _appSettings;
    public MyClass(IOptions<AppSettings> appSettings) {
        _appSettings = appSettings.Value;
    }
    
        4
  •  1
  •   brainoverflow98    5 年前

    这就是我绑定设置对象并将其作为单例添加到中的方式。Net Core 3.0

    public void ConfigureServices(IServiceCollection services)
            {
                var jwtSettings = new JwtSettings();
                Configuration.Bind(jwtSettings);
                services.AddSingleton(jwtSettings);
    
                var databaseSettings = new DatabaseSettings();
                Configuration.Bind(databaseSettings);
                services.AddSingleton(databaseSettings);
    
    
                services.AddControllersWithViews();
            }
    

    我的设置对象如下所示:

    public class DatabaseSettings
        {
            public string ConnectionString { get; set; }
            public string DatabaseName { get; set; }
        }
    
    public class JwtSettings
        {
            public string Secret { get; set; }
            public string Lifetime { get; set; }
        }
    

    我的应用程序设置。json文件如下所示:

    {
      "DatabaseSettings": {
        "ConnectionString": "mongodb://localhost:27017",
        "DatabaseName": "TestDb"
      },
      "JwtSettings": {
        "Secret": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
        "Lifetime": "170"
      },
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft": "Warning",
          "Microsoft.Hosting.Lifetime": "Information"
        }
      },
      "AllowedHosts": "*"
    }
    
        5
  •  0
  •   Oliver    7 年前

    为了更简单的配置,我创建了一个助手类,该类扫描配置对象中的嵌套配置,然后尝试在加载的程序集中找到相应的类,并使用给定的配置对其进行初始化。

    appsettings。json:

    {
        "MyState": {
            "SomeSimpleValue": "Hello World",
            "MyTimeSpan": "00:15:00"
        }
    }
    

    MyStateOptions。反恐精英

    // Class has same name as in appsettings.json with Options suffix.
    public class MyStateOptions
    {
        // Properties must be deserializable from string
        // or a class with a default constructor that has
        // only properties that are deserializable from string.
        public string SomeSimpleValue { get; set; }
        public DateTime MyTimeSpan { get; set; }
    }
    

    启动。反恐精英

    public class Startup
    {
        public IConfigurationRoot Configuration { get; }
    
        public Startup(IHostingEnvironment env)
        {
            // Create configuration as you need it...
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile(...)
                .AddEnvironmentVariables();
    
            // Save configuration in property to access it later.
            Configuration = builder.Build();
        }
    
        public void ConfigureServices(IServiceCollection services)
        {
            // Register all your desired services...
            services.AddMvc(options => ...);
    
            // Call our helper method
            services.RegisterOptions(Configuration);
        }
    }
    

    HelperClass。反恐精英

    public static class IServiceCollectionExtensions
    {
        public static void RegisterOptions(
            this IServiceCollection services,
            IConfiguration configuration)
        {
            // Create all options from the given configuration.
            var options = OptionsHelper.CreateOptions(configuration);
    
            foreach (var option in options)
            {
                // We get back Options<MyOptionsType> : IOptions<MyOptionsType>
                var interfaces = option.GetType().GetInterfaces();
    
                foreach (var type in interfaces)
                {
                    // Register options IServiceCollection
                    services.AddSingleton(type, option);
                }
            }
        }
    }
    

    选项帮助器。反恐精英

    public static class OptionsHelper
    {
        public static IEnumerable<object> CreateOptions(IConfiguration configuration)
        {
            // Get all sections that are objects:
            var sections = configuration.GetChildren()
                .Where(section => section.GetChildren().Any());
    
           foreach (var section in sections)
           {
               // Add "Options" suffix if not done.
               var name = section.Key.EndsWith("Options")
                   ? section.Key 
                   : section.Key + "Options";
               // Scan AppDomain for a matching type.
               var type = FirstOrDefaultMatchingType(name);
    
               if (type != null)
               {
                   // Use ConfigurationBinder to create an instance with the given data.
                   var settings = section.Get(type);
                   // Encapsulate instance in "Options<T>"
                   var options = CreateOptionsFor(settings);
               }
           }
        }
    
        private static Type FirstOrDefaultMatchingType(string typeName)
        {
            // Find matching type that has a default constructor
            return AppDomain.CurrentDomain.GetAssemblies()
                .Where(assembly => !assembly.IsDynamic)
                .SelectMany(assembly => assembly.GetTypes())
                .Where(type => type.Name == typeName)
                .Where(type => !type.IsAbstract)
                .Where(type => type.GetMatchingConstructor(Type.EmptyTypes) != null)
                .FirstOrDefault();
        }
    
        private static object CreateOptionsFor(object settings)
        {
            // Call generic method Options.Create<TOptions>(TOptions options)
            var openGeneric = typeof(Options).GetMethod(nameof(Options.Create));
            var method = openGeneric.MakeGenericMethod(settings.GetType());
    
            return method.Invoke(null, new[] { settings });
        }
    }
    

    完成所有这些工作后,您可以在服务集合中拥有一个服务,该服务在其构造函数中要求 IOptions<MyStateOptions> 您将获得它,而无需显式配置您拥有的每个选项。只需使用所需的服务和选项实例创建一个新项目。将项目添加到主项目,并将所需配置添加到appsettings。json。

    示例服务。反恐精英

    public class MyExampleService
    {
        private readonly MyStateOptions _options;
    
        public MyExampleService(IOptions<MyStateOptions> options)
        {
            _options = options?.Value ?? throw new ArgumentNullException(nameof(options));
        }
    }