前言

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

ASP.NET Core 选项模式源码学习Options IOptions(二)的更多相关文章

  1. ASP.NET Core 选项模式源码学习Options Configure(一)

    前言 ASP.NET Core 后我们的配置变得更加轻量级了,在ASP.NET Core中,配置模型得到了显著的扩展和增强,应用程序配置可以存储在多环境变量配置中,appsettings.json用户 ...

  2. ASP.NET Core 选项模式源码学习Options IOptionsMonitor(三)

    前言 IOptionsMonitor 是一种单一示例服务,可随时检索当前选项值,这在单一实例依赖项中尤其有用.IOptionsMonitor用于检索选项并管理TOption实例的选项通知, IOpti ...

  3. ASP.NET Core 2.1 源码学习之 Options[1]:Configure

    配置的本质就是字符串的键值对,但是对于面向对象语言来说,能使用强类型的配置是何等的爽哉! 目录 ASP.NET Core 配置系统 强类型的 Options Configure 方法 Configur ...

  4. ASP.NET Core 2.1 源码学习之 Options[3]:IOptionsMonitor

    前面我们讲到 IOptions 和 IOptionsSnapshot,他们两个最大的区别便是前者注册的是单例模式,后者注册的是 Scope 模式.而 IOptionsMonitor 则要求配置源必须是 ...

  5. ASP.NET Core 2.1 源码学习之 Options[3]:IOptionsMonitor 【转】

    原文链接:https://www.cnblogs.com/RainingNight/p/strongly-typed-options-ioptions-monitor-in-asp-net-core. ...

  6. ASP.NET Core 2.1 源码学习之 Options[1]:Configure 【转】

    原文链接:https://www.cnblogs.com/RainingNight/p/strongly-typed-options-configure-in-asp-net-core.html 配置 ...

  7. ASP.NET Core 2.1 源码学习之 Options[2]:IOptions

    在 上一章 中,介绍了Options的注册,而在使用时只需要注入 IOption<T> 即可: public ValuesController(IOptions<MyOptions& ...

  8. ASP.NET Core 2.1 源码学习之 Options[2]:IOptions 【转】

    原文链接:https://www.cnblogs.com/RainingNight/p/strongly-typed-options-ioptions-in-asp-net-core.html 在 上 ...

  9. .NET Core 2.1 源码学习:看 SocketsHttpHandler 如何在异步方法中连接 Socket

    在 .NET Core 2.1 中,System.Net.Sockets 的性能有了很大的提升,最好的证明是 Kestrel 与 HttpClient 都改为使用 System.Net.Sockets ...

随机推荐

  1. UiPath之DataTable转换为List和Array

    今天给大家分享一下,如何将DataTable转为List和Array,为此小U也花了不少时间研究,最后发现没有那么复杂. 先来说说List和Array的区别: List:就像一个链条,存储数据的空间可 ...

  2. T-SQL Part VI: Prevent error message "Saving changes is not permitted" in SSMS

    使用SSMS时,经常遇到的问题是,修改一张table时,弹出一个错误对话框:“Saving changes is not permitted”. 这个错误通常是因为以下错误(参阅MSDN的KB文档 h ...

  3. [javascript] 编写一个计算器,实现加减法

    1.代码 <script> function sum(){ //加法 var value1 = document.getElementById("num1").valu ...

  4. 本地Git连接GitLab(服务器)远程仓库

    1.简介 远程仓库是指托管在网络上的项目仓库,现在互联网上有很多项目托管平台,比如github.gitlab等.为了不公开自己项目代码,可以在自己的服务器上搭建自己的项目仓库,最常见的是搭建GitLa ...

  5. pat 1100 Mars Numbers(20 分)

    1100 Mars Numbers(20 分) People on Mars count their numbers with base 13: Zero on Earth is called &qu ...

  6. pat 1120 Friend Numbers(20 分)

    1120 Friend Numbers(20 分) Two integers are called "friend numbers" if they share the same ...

  7. React入门知识点清单

    做前端的一定都知道现在是三大框架--Vue.React.Angular三足鼎立的时代.Vue是公认的最容易入门的,因为它文件结构上有传统的HTML的影子,让刚接触它的前端人员刚到很"亲切&q ...

  8. 安装win7和ubuntu16.04双系统

    硬件:2012年本子  话硕A55V Service 准备: 首先通过一键还原备份win7系统!不清楚某些失误会不会备份也不能拯救! 清出100g硬盘空间,ubuntu会安装在这里 查看当前win7启 ...

  9. 简单地迁移你的android jni代码逻辑到iOS - 编写iOS下jni.h的替代 - ocni.h

    1. jni的代码逻辑中与上层平台语言交互了. 2. 使用非Xcode的ide开发工具,希望使用纯净的c/c++代码,不掺杂其它平台相关的语言语法. 3. 只想简单地替换jni代码对上层平台语言的功能 ...

  10. 学习记录:《C++设计模式——李建忠主讲》2.面向对象设计原则

    1.课程内容: 重新认识面向对象:面向对象设计原则: 2.重新认识面向对象 1)理解隔离变化:从宏观层面来看,面向对象的构建方式更能适应软件的变化,将变化所带来的影响减为最小: 2)各司其职:从微观层 ...