• ASP.NET Core 选项模式源码学习Options IOptions(二)


    前言

    上一篇文章介绍IOptions的注册,本章我们继续往下看

    IOptions

    IOptions是一个接口里面只有一个Values属性,该接口通过OptionsManager实现

    
       public interface IOptions<out TOptions> where TOptions : class, new()
        {
            /// <summary>
            /// The default configured <typeparamref name="TOptions"/> instance
            /// </summary>
            TOptions Value { get; }
        }
    
    

    OptionsManager

    OptionsManager实现了IOptions<>和IOptionsSnapshot<>,他使用内部属性OptionsCache 进行缓存操作;实现IOptionsSnapshot接口Get(string name)其实就是获取我们第一章所指定的Name,通过IOptionsFactory<>创建TOptions实例

        public class OptionsManager<TOptions> : IOptions<TOptions>, IOptionsSnapshot<TOptions> where TOptions : class, new()
        {
            private readonly IOptionsFactory<TOptions> _factory;
            private readonly OptionsCache<TOptions> _cache = new OptionsCache<TOptions>(); // Note: this is a private cache
    
            /// <summary>
            /// Initializes a new instance with the specified options configurations.
            /// </summary>
            /// <param name="factory">The factory to use to create options.</param>
            public OptionsManager(IOptionsFactory<TOptions> factory)
            {
                _factory = factory;
            }
    
            /// <summary>
            /// The default configured <typeparamref name="TOptions"/> instance, equivalent to Get(Options.DefaultName).
            /// </summary>
            public TOptions Value
            {
                get
                {
                    return Get(Options.DefaultName);
                }
            }
    
            /// <summary>
            /// Returns a configured <typeparamref name="TOptions"/> instance with the given <paramref name="name"/>.
            /// </summary>
            public virtual TOptions Get(string name)
            {
                name = name ?? Options.DefaultName;
    
                // Store the options in our instance cache
                return _cache.GetOrAdd(name, () => _factory.Create(name));
            }
        }
        
            public interface IOptionsSnapshot<out TOptions> : IOptions<TOptions> where TOptions : class, new()
        {
            /// <summary>
            /// Returns a configured <typeparamref name="TOptions"/> instance with the given name.
            /// </summary>
            TOptions Get(string name);
        }
    
    

    OptionsCache

    OptionsCache采用了线程安全字典ConcurrentDictionary进行了封装用于内存缓存

    
        public class OptionsCache<TOptions> : IOptionsMonitorCache<TOptions> where TOptions : class
        {
            private readonly ConcurrentDictionary<string, Lazy<TOptions>> _cache = new ConcurrentDictionary<string, Lazy<TOptions>>(StringComparer.Ordinal);
    
            /// <summary>
            /// Clears all options instances from the cache.
            /// </summary>
            public void Clear() => _cache.Clear();
    
            /// <summary>
            /// Gets a named options instance, or adds a new instance created with <paramref name="createOptions"/>.
            /// </summary>
            /// <param name="name">The name of the options instance.</param>
            /// <param name="createOptions">The func used to create the new instance.</param>
            /// <returns>The options instance.</returns>
            public virtual TOptions GetOrAdd(string name, Func<TOptions> createOptions)
            {
                if (createOptions == null)
                {
                    throw new ArgumentNullException(nameof(createOptions));
                }
                name = name ?? Options.DefaultName;
                return _cache.GetOrAdd(name, new Lazy<TOptions>(createOptions)).Value;
            }
    
            /// <summary>
            /// Tries to adds a new option to the cache, will return false if the name already exists.
            /// </summary>
            /// <param name="name">The name of the options instance.</param>
            /// <param name="options">The options instance.</param>
            /// <returns>Whether anything was added.</returns>
            public virtual bool TryAdd(string name, TOptions options)
            {
                if (options == null)
                {
                    throw new ArgumentNullException(nameof(options));
                }
                name = name ?? Options.DefaultName;
                return _cache.TryAdd(name, new Lazy<TOptions>(() => options));
            }
    
            /// <summary>
            /// Try to remove an options instance.
            /// </summary>
            /// <param name="name">The name of the options instance.</param>
            /// <returns>Whether anything was removed.</returns>
            public virtual bool TryRemove(string name)
            {
                name = name ?? Options.DefaultName;
                return _cache.TryRemove(name, out var ignored);
            }
        }
    
    

    OptionsFactory

    OptionsFactory实现了 IOptionsFactory.Create(string name);,
    而OptionsFactory构造函数中注入了IConfigureOptions<>和IPostConfigureOptions<>,
    这里使用了IEnumerable类型标识当注册多个时候按照次数依次的执行,从如下代码中我们也看到了我们在上一章中所说的Configures和postConfigures注册先后顺序问题。

    
        public class OptionsFactory<TOptions> : IOptionsFactory<TOptions> where TOptions : class, new()
        {
            private readonly IEnumerable<IConfigureOptions<TOptions>> _setups;
            private readonly IEnumerable<IPostConfigureOptions<TOptions>> _postConfigures;
            private readonly IEnumerable<IValidateOptions<TOptions>> _validations;
    
            public OptionsFactory(IEnumerable<IConfigureOptions<TOptions>> setups, IEnumerable<IPostConfigureOptions<TOptions>> postConfigures) : this(setups, postConfigures, validations: null)
            { }
    
           
          
            public OptionsFactory(IEnumerable<IConfigureOptions<TOptions>> setups, IEnumerable<IPostConfigureOptions<TOptions>> postConfigures, IEnumerable<IValidateOptions<TOptions>> validations)
            {
                _setups = setups;
                _postConfigures = postConfigures;
                _validations = validations;
            }
    
           
            public TOptions Create(string name)
            {
                var options = new TOptions();
                foreach (var setup in _setups)
                {
                    if (setup is IConfigureNamedOptions<TOptions> namedSetup)
                    {
                        namedSetup.Configure(name, options);
                    }
                    else if (name == Options.DefaultName)
                    {
                        setup.Configure(options);
                    }
                }
                foreach (var post in _postConfigures)
                {
                    post.PostConfigure(name, options);
                }
    
                if (_validations != null)
                {
                    var failures = new List<string>();
                    foreach (var validate in _validations)
                    {
                        var result = validate.Validate(name, options);
                        if (result.Failed)
                        {
                            failures.AddRange(result.Failures);
                        }
                    }
                    if (failures.Count > 0)
                    {
                        throw new OptionsValidationException(name, typeof(TOptions), failures);
                    }
                }
    
                return options;
            }
        }
    
    
  • 相关阅读:
    网页尺寸scrollHeight
    浏览器窗口可视区域大小
    创建文本节点createTextNode
    创建元素节点createElement
    faster rcnn需要理解的地方
    3d点云
    多维的vector定义和初始化
    写代码的可扩展性
    1111
    tmux命令
  • 原文地址:https://www.cnblogs.com/yyfh/p/12032983.html
Copyright © 2020-2023  润新知