ASP.NET Coreオプションモードソースコード学習Options Configure(一)

6593 ワード

前言

ASP.NET Coreの後、私たちの配置はもっと軽量級になりました.ASP.NET Coreでは、構成モデルが大幅に拡張され、強化され、アプリケーション構成が多環境変数構成に格納され、appsettings.jsonユーザ機密などは、アプリケーション内の同じインタフェースで簡単にアクセスできるほか、ASP.NETの新しい構成システムでは、Optionsの強いタイプ設定を使用できます.
強いタイプOptions

ASP.NET CoreにAppSettings[Key]のデフォルトメソッドがない場合は、強いタイプの構成クラスを作成し、構成項目をバインドすることをお勧めします.

    public class MyOptions
    {
        public string Name { get; set; }

        public string Url { get; set; }
    }

そしてappsettingsでjsonには次の内容が追加されます.

{
  "MyOptions": 
    {
      "Name": "TestName",
      "Url": "TestUrl"
    }
}

クラスへのバインドの設定

コンフィギュレーションサービスメソッドは、クラスにバインドするように構成されています.
        public void ConfigureServices(IServiceCollection services)
        {

            services.Configure(Configuration.GetSection("MyOptions"));
            services.AddControllers();

        }

MyOptionsは、IOptions<>クラスのインスタンスをコントローラに注入し、ValueプロパティでMyoptionsを取得するだけです.

    public class WeatherForecastController : ControllerBase
    {
        private readonly MyOptions _options;
        public WeatherForecastController(IOptions options)
        {
            _options = options.Value;
        }

        [HttpGet]
        public OkObjectResult Get() {
            return Ok(string.Format("Name:{0},Url:{1}", _options.Name,_options.Url));
        }
    }

Configure

委任構成

            //      
            services.Configure(o => { o.Url = "MyOptions"; o.Name = "Name111"; });
            //      
            services.Configure("Option", o => { o.Url = "MyOptions"; o.Name = "Name111"; }) ;
            //      
            services.ConfigureAll(options =>{ options.Name = "Name1";  options.Url = "Url1";});


プロファイルによる構成

           //            
            services.Configure(Configuration.GetSection("MyOptions"));
            //       
            services.Configure("Option", Configuration.GetSection("MyOptions"));

PostConfigure
PostConfigureは、Configureの登録が完了してから登録されます

     services.PostConfigure(o => o.Name = "Name1");
            services.PostConfigure("Option", o => o.Name = "Name1");
            services.PostConfigureAll(o => o.Name = "Name1");

ソース解析

IConfigureOptionsインタフェース

    public interface IConfigureOptions where TOptions : class
    {
        
        void Configure(TOptions options);
    }


コンフィギュレーションIConfigureOptionsの登録を容易にするための例コンフィギュレーションNamedOptions

     public static IServiceCollection Configure(this IServiceCollection services, string name, Action configureOptions)
            where TOptions : class
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            if (configureOptions == null)
            {
                throw new ArgumentNullException(nameof(configureOptions));
            }

            services.AddOptions();
            services.AddSingleton>(new ConfigureNamedOptions(name, configureOptions));
            return services;
        }



上記のコードIConfigureOptionsはコンフィギュレーション名edOptionsを実現しています.では、内部ソースのコンフィギュレーション名edOptionsは、私たちが登録したActionを統合したコンフィギュレーションメソッドにパッケージして、後でOptionsインスタンスを作成するときに初期化を容易にします.

    public class ConfigureNamedOptions : IConfigureNamedOptions where TOptions : class
    {
        
        public ConfigureNamedOptions(string name, Action action)
        {
            Name = name;
            Action = action;
        }

       
        public string Name { get; }

      
        public Action Action { get; }

      
        public virtual void Configure(string name, TOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            // Null name is used to configure all named options.
            if (Name == null || name == Name)
            {
                Action?.Invoke(options);
            }
        }
        public void Configure(TOptions options) => Configure(Options.DefaultName, options);
    }

サービスでConfigure (Configuration.GetSection("MyOptions")); 具体的な名前を指定しない場合、デフォルトは次のコードクリップです.

        public virtual void Configure(string name, TOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            // Null name is used to configure all named options.
            if (Name == null || name == Name)
            {
                Action?.Invoke(options);
            }
        }
        public void Configure(TOptions options) => Configure(Options.DefaultName, options);

デフォルトではOptionsが使用されています.DefaultName
AddOptionsのデフォルトメソッドでは、いくつかのコアクラスが登録されています.

     public static IServiceCollection AddOptions(this IServiceCollection services)
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            services.TryAdd(ServiceDescriptor.Singleton(typeof(IOptions<>), typeof(OptionsManager<>)));
            services.TryAdd(ServiceDescriptor.Scoped(typeof(IOptionsSnapshot<>), typeof(OptionsManager<>)));
            services.TryAdd(ServiceDescriptor.Singleton(typeof(IOptionsMonitor<>), typeof(OptionsMonitor<>)));
            services.TryAdd(ServiceDescriptor.Transient(typeof(IOptionsFactory<>), typeof(OptionsFactory<>)));
            services.TryAdd(ServiceDescriptor.Singleton(typeof(IOptionsMonitorCache<>), typeof(OptionsCache<>)));
            return services;
        }