这里先 说一下 In 和 Out
in 向内部变化 向父类变化发展 “逆变”->”逆常的变” <string>=<object>;
out 向外部变化 向子类变化发展 “协变”->”和谐的变” <object>=<string>;
看一下 In 的例子:
// Contravariant interface.
interface IContravariant<in A> { }
// Extending contravariant interface.
interface IExtContravariant<in A> : IContravariant<A> { }
// Implementing contravariant interface.
class Sample<A> : IContravariant<A> { }
class Program
{
static void Test()
{
IContravariant<Object> iobj = new Sample<Object>();
IContravariant<String> istr = new Sample<String>();
// You can assign iobj to istr because
// the IContravariant interface is contravariant.
istr = iobj;
}
}
再看一下 out 的例子:
// Covariant interface.
interface ICovariant<out R> { }
// Extending covariant interface.
interface IExtCovariant<out R> : ICovariant<R> { }
// Implementing covariant interface.
class Sample<R> : ICovariant<R> { }
class Program
{
static void Test()
{
ICovariant<Object> iobj = new Sample<Object>();
ICovariant<String> istr = new Sample<String>();
// You can assign istr to iobj because
// the ICovariant interface is covariant.
iobj = istr;
}
}
接口代码:
public interface IOptions<out TOptions> where TOptions : class,new()
{
TOptions Options { get; }
TOptions GetNamedOptions(string name);
}
这里 实现这个接口的类有一个:
public class OptionsManager<TOptions> : IOptions<TOptions> where TOptions : class,new()
看一下具体的代码:
public class OptionsManager<TOptions> : IOptions<TOptions> where TOptions : class,new()
{
private object _mapLock = new object();
private Dictionary<string, TOptions> _namedOptions = new Dictionary<string, TOptions>(StringComparer.OrdinalIgnoreCase);
private IEnumerable<IConfigureOptions<TOptions>> _setups;
/// <summary>
/// 这里是由依赖注入来传入参数的 所有实现 IConfigureOptions<TOptions> 并且添加到ServiceCollection里的对象。
/// </summary>
/// <param name="setups"></param>
public OptionsManager(IEnumerable<IConfigureOptions<TOptions>> setups)
{
_setups = setups;
}
public virtual TOptions GetNamedOptions([NotNull] string name)
{
/*
这里采用了 double check locking
lock 里面的 判断是必须的
lock 外面的 判断可以没有 但是有的话 可以提高性能 避免都在Lock内部判断
*/
if (!_namedOptions.ContainsKey(name))
{
lock (_mapLock)
{
if (!_namedOptions.ContainsKey(name))
{
_namedOptions[name] = Configure(name);
}
}
}
return _namedOptions[name];
}
public virtual TOptions Configure(string optionsName = "")
{
return _setups == null
? new TOptions()
: _setups.OrderBy(setup => setup.Order)
.Aggregate(new TOptions(),
(options, setup) =>
{
setup.Configure(options, optionsName);
return options;
});
/*
IEnumerable<IConfigureOptions<TOptions>> setups;
首先将集合排序
看一下 Aggregate 的源代码:
public static TAccumulate Aggregate<TSource, TAccumulate>(this IEnumerable<TSource> source, TAccumulate seed
, Func<TAccumulate, TSource, TAccumulate> func) {
if (source == null) throw Error.ArgumentNull("source");
if (func == null) throw Error.ArgumentNull("func");
TAccumulate result = seed;
foreach (TSource element in source) result = func(result, element);
return result;
}
结合源代码来理解:
TOptions result =new TOptions();如果集合为空 就返回这个了;
foreach(IConfigureOptions<TOptions> setup in _setups)
{
//名字匹配才会执行
setup.Configure(result, optionsName);
}
return result;
*/
}
public virtual TOptions Options
{
get
{
return GetNamedOptions("");
}
}
}
浙公网安备 33010602011771号