[Asp.net 5] Options-configuration file (2), asp. netoptions-
I wrote an article about Options a long time ago. I opened it again in 2016 and found many changes. Added new classes and OptionMonitor-related classes. Today we will introduce the so-called new version.
The old version of the portal ([Asp.net 5] Options-configuration after the configuration file ).
First, the previous figure:
* The green line is an inheritance relationship, and the blue line is an association relationship.
We cut the top into 2 parts.
Option
This part is divided into two parts. The first part directly creates Options. This part creates an OptionsWrapper class through the Options static class, and then injects (IOptions, OptionsWrapper. This part is the entity injection of DI. It is very simple and there is nothing to say. Here the application is very common"Factory Model".
The second part is to inject (IOptions, OptionsManager. OptionsManager uses IEnumerable <IConfigureOptions <TOptions> as the parameter, and internally returns OptionsCache-type objects.Proxy Mode"
Internal class OptionsCache <TOptions> where TOptions: class, new () {private readonly Func <TOptions> _ createCache; private object _ cacheLock = new object (); private bool _ cacheInitialized; private TOptions _ options; private IEnumerable <IConfigureOptions <TOptions> _ setups; public OptionsCache (IEnumerable <IConfigureOptions <TOptions> setups) {_ setups = setups; _ createCache = CreateOptions ;} priva Te TOptions CreateOptions () {var result = new TOptions (); if (_ setups! = Null) {foreach (var setup in _ setups) {setup. configure (result) ;}} return result;} public virtual TOptions Value {get {return LazyInitializer. ensureInitialized (ref _ options, ref _ cacheInitialized, ref _ cacheLock, _ createCache );}}}OptionsCache
Here, the OptionsCache code in the appendix (IConfigureOptions, ConfigureOptions) has been injected. The ConfigureOptions code is as follows:
Public class ConfigureOptions <TOptions>: IConfigureOptions <TOptions> where TOptions: class {public ConfigureOptions (Action <TOptions> action) {if (action = null) {throw new ArgumentNullException (nameof (action);} Action = action;} public Action <TOptions> Action {get; private set;} public virtual void Configure (TOptions options) {if (options = null) {throw new ArgumentNullException (nameof (options);} Action. invoke (options );}}ConfigureOptions
ConfigureOptions is actually an encapsulation of Action <TOptions> (can it be understoodAdapter).
* Why Should I pass the Action <T> for configuration? My understanding is thatLatency.The concept of latency is that the changes you make do not take effect immediately, so that we do not have to consider the order of configuration.
OptionsMonitor
OptionsMonitor is a monitor for Options. I decided this part is likeDispatcher mode ??.
OfIOptionsChangeTokenSource
The OptionsMonitor code is as follows:
Public class OptionsMonitor <TOptions>: IOptionsMonitor <TOptions> where TOptions: class, new () {private OptionsCache <TOptions> _ optionsCache; private readonly IEnumerable <IConfigureOptions <TOptions> _ setups; private readonly IEnumerable <strong <TOptions> _ sources; public OptionsMonitor (IEnumerable <IConfigureOptions <TOptions> setups, IEnumerable <strong <TOptions> sources) {_ sources = sources; _ setups = setups; _ optionsCache = new OptionsCache <TOptions> (setups);} public TOptions CurrentValue {get {return _ optionsCache. value ;}} public IDisposable OnChange (Action <TOptions> listener) {var disposable = new ChangeTrackerDisposable (); foreach (var source in _ sources) {Action <object> callback = null; IDisposable previussubscription = null; callback = (s) => {// The order here is important. we need to take the token and then apply our changes BEFORE // registering. this prevents us from possible having two change updates to process concurrently. /// If the token changes after we take the token, then we'll process the update immediately upon // registering the callback. var token = source. getChangeToken (); // Recompute the options before calling the watchers _ optionsCache = new OptionsCache <TOptions> (_ setups); listener (_ optionsCache. value); // Remove the old callback after its been fired var nextSubscription = token. registerChangeCallback (callback, s); disposable. disposables. add (nextsubable); disposable. disposables. remove (previussubscription); previussubscription = nextSubscription ;}; previussubsource = source. getChangeToken (). registerChangeCallback (callback, state: null); disposable. disposables. add (previussubable);} return disposable ;}}OptionsMonitor
Use the IChangeToken object of IOptionsChangeTokenSource to send a change request. Then, the Action <TOptions> listener changes the data.
The Onchange method is implemented by creating a new IDisposable (ChangeTrackerDisposable) for each call.