当前位置: 移动技术网 > IT编程>开发语言>.net > ASP.NET Core 选项模式源码学习Options IOptions(二)

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

2019年12月13日  | 移动技术网IT编程  | 我要评论

邪恶动态图片27,武迪生,黄致列假图吹嘘

前言

上一篇文章介绍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;
        }
    }

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网