一、目录
<h1 style="text-align: center;">《Effective C#》快速笔记 - C# 中的动态编程 <img style="max-width: 100%;" src="https://www.52php.cn/res/2019/01-27/18/447a0be01a1699650c015e43e769b8c7.png" alt=""> 静态类型和动态类型各有所长,静态类型能够让编译器帮你找出更多的错误,因为编译器能够在编译时进行大部分的检查工作。C# 是一种静态类型的语言,不过它加入了动态类型的语言特性,可以更高效地解决问题。 一、目录
三十八、理解动态类型的优劣
这里,我使用 3 种数字相加的方法,dynamic 动态、Func 委托以及使用表达式树进行相加的区别: result1 = AddDynamic(,
</span><span style="color: #0000ff;">var</span> result2 = AddFunc(<span style="color: #800080;">3</span>,<span style="color: #800080;">4</span>,(x,y) => x +<span style="color: #000000;"> y);
Console.WriteLine(result2);
</span><span style="color: #0000ff;">var</span> result3 = AddExpressionTree(<span style="color: #800080;">4</span>,<span style="color: #800080;">5</span><span style="color: #000000;">);
Console.WriteLine(result3);
}
</span><span style="color: #808080;">///</span> <span style="color: #808080;"><summary></span>
<span style="color: #808080;">///</span><span style="color: #008000;"> Add,动态
</span><span style="color: #808080;">///</span> <span style="color: #808080;"></summary></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><param name="a"></param></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><param name="b"></param></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><returns></returns></span>
<span style="color: #0000ff;">private</span> <span style="color: #0000ff;">dynamic</span> AddDynamic(<span style="color: #0000ff;">dynamic</span> a,<span style="color: #0000ff;">dynamic</span><span style="color: #000000;"> b)
{
</span><span style="color: #0000ff;">return</span> a +<span style="color: #000000;"> b;
}
</span><span style="color: #808080;">///</span> <span style="color: #808080;"><summary></span>
<span style="color: #808080;">///</span><span style="color: #008000;"> Add,使用委托
</span><span style="color: #808080;">///</span> <span style="color: #808080;"></summary></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><typeparam name="T1"></typeparam></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><typeparam name="T2"></typeparam></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><typeparam name="TR"></typeparam></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><param name="a"></param></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><param name="b"></param></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><param name="func"></param></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><returns></returns></span>
<span style="color: #0000ff;">private</span> TR AddFunc<T1,T2,TR>(T1 a,T2 b,Func<T1,TR><span style="color: #000000;"> func)
{
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> func(a,b);
}
</span><span style="color: #808080;">///</span> <span style="color: #808080;"><summary></span>
<span style="color: #808080;">///</span><span style="color: #008000;"> Add,使用表达式树
</span><span style="color: #808080;">///</span> <span style="color: #808080;"></summary></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><typeparam name="T"></typeparam></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><param name="a"></param></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><param name="b"></param></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><returns></returns></span>
<span style="color: #0000ff;">private</span> T AddExpressionTree<T><span style="color: #000000;">(T a,T b)
{
ParameterExpression leftOperand </span>= Expression.Parameter(<span style="color: #0000ff;">typeof</span>(T),<span style="color: #800000;">"</span><span style="color: #800000;">left</span><span style="color: #800000;">"</span><span style="color: #000000;">);
ParameterExpression rightOperand </span>= Expression.Parameter(<span style="color: #0000ff;">typeof</span>(T),<span style="color: #800000;">"</span><span style="color: #800000;">right</span><span style="color: #800000;">"</span><span style="color: #000000;">);
BinaryExpression body </span>=<span style="color: #000000;"> Expression.Add(leftOperand,rightOperand);
Expression</span><Func<T,T,T>> adder = Expression.Lambda<Func<T,T>><span style="color: #000000;">(body,leftOperand,rightOperand);
Func</span><T,T> theDelegate =<span style="color: #000000;"> adder.Compile();
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> theDelegate(a,b);
}
}</span></pre>
三十九、使用动态类型表达泛型类型参数的运行时类型
四十、将接受匿名类型的参数声明为 dynamic
四十一、用 DynamicObject 或 IDynamicMetaObjectProvider 实现数据驱动的动态类型
这是一个实现动态类型模型的一个示例。除了需要继承 DynamicObject,还需要重写 TryGetMemebr() 和 TrySetMemebr()。 propDynamic = =
Console.WriteLine(propDynamic.Now);
}
</span><span style="color: #808080;">///</span> <span style="color: #808080;"><summary></span>
<span style="color: #808080;">///</span><span style="color: #008000;"> 动态属性绑定模型
</span><span style="color: #808080;">///</span> <span style="color: #808080;"></summary></span>
<span style="color: #0000ff;">internal</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> DynamicPropertyBag : DynamicObject
{
</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">readonly</span> Dictionary<<span style="color: #0000ff;">string</span>,<span style="color: #0000ff;">object</span>> _storage = <span style="color: #0000ff;">new</span> Dictionary<<span style="color: #0000ff;">string</span>,<span style="color: #0000ff;">object</span>><span style="color: #000000;">();
</span><span style="color: #808080;">///</span> <span style="color: #808080;"><summary></span>
<span style="color: #808080;">///</span><span style="color: #008000;"> 获取属性值
</span><span style="color: #808080;">///</span> <span style="color: #808080;"></summary></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><param name="binder"></param></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><param name="result"></param></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><returns></returns></span>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">override</span> <span style="color: #0000ff;">bool</span> TryGetMember(GetMemberBinder binder,<span style="color: #0000ff;">out</span> <span style="color: #0000ff;">object</span><span style="color: #000000;"> result)
{
</span><span style="color: #0000ff;">var</span> key =<span style="color: #000000;"> binder.Name;
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (_storage.ContainsKey(key))
{
result </span>=<span style="color: #000000;"> _storage[key];
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #000000;">;
}
result </span>= <span style="color: #0000ff;">null</span><span style="color: #000000;">;
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #000000;">;
}
</span><span style="color: #808080;">///</span> <span style="color: #808080;"><summary></span>
<span style="color: #808080;">///</span><span style="color: #008000;"> 设置属性值
</span><span style="color: #808080;">///</span> <span style="color: #808080;"></summary></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><param name="binder"></param></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><param name="value"></param></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><returns></returns></span>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">override</span> <span style="color: #0000ff;">bool</span> TrySetMember(SetMemberBinder binder,<span style="color: #0000ff;">object</span><span style="color: #000000;"> value)
{
</span><span style="color: #0000ff;">var</span> key =<span style="color: #000000;"> binder.Name;
</span><span style="color: #0000ff;">try</span><span style="color: #000000;">
{
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (_storage.ContainsKey(key))
{
_storage[key] </span>=<span style="color: #000000;"> value;
}
</span><span style="color: #0000ff;">else</span><span style="color: #000000;">
{
_storage.Add(key,value);
}
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #000000;">;
}
</span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (Exception e)
{
Console.WriteLine(e);
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #000000;">;
}
}</span></pre>
? 四十二、如何使用表达式 API
这里提供了一个示例: result = Call<,>((x) => (x * ).ToString(
Console.WriteLine(result);
}
</span><span style="color: #808080;">///</span> <span style="color: #808080;"><summary></span>
<span style="color: #808080;">///</span><span style="color: #008000;"> 调用
</span><span style="color: #808080;">///</span> <span style="color: #808080;"></summary></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><typeparam name="T"></typeparam></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><typeparam name="TResult"></typeparam></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><param name="op"></param></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><returns></returns></span>
<span style="color: #0000ff;">private</span> TResult Call<T,TResult>(Expression<Func<T,TResult>><span style="color: #000000;"> op)
{
</span><span style="color: #0000ff;">var</span> exp = op.Body <span style="color: #0000ff;">as</span><span style="color: #000000;"> MethodCallExpression;
</span><span style="color: #0000ff;">var</span> result = <span style="color: #0000ff;">default</span><span style="color: #000000;">(TResult);
</span><span style="color: #0000ff;">if</span> (exp == <span style="color: #0000ff;">null</span><span style="color: #000000;">)
{
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> result;
}
</span><span style="color: #0000ff;">var</span> methodName =<span style="color: #000000;"> exp.Method.Name;
</span><span style="color: #0000ff;">var</span> parameters =<span style="color: #000000;"> exp.Arguments.Select(ProcessArgument);
Console.WriteLine($</span><span style="color: #800000;">"</span><span style="color: #800000;">方法名 {methodName}</span><span style="color: #800000;">"</span><span style="color: #000000;">);
</span><span style="color: #0000ff;">foreach</span> (<span style="color: #0000ff;">var</span> parameter <span style="color: #0000ff;">in</span><span style="color: #000000;"> parameters)
{
Console.WriteLine(</span><span style="color: #800000;">"</span><span style="color: #800000;">参数:</span><span style="color: #800000;">"</span><span style="color: #000000;">);
Console.WriteLine($</span><span style="color: #800000;">"</span><span style="color: #800000;">t{parameter.Item1}:{parameter.Item2}</span><span style="color: #800000;">"</span><span style="color: #000000;">);
}
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> result;
}
</span><span style="color: #808080;">///</span> <span style="color: #808080;"><summary></span>
<span style="color: #808080;">///</span><span style="color: #008000;"> 处理参数
</span><span style="color: #808080;">///</span> <span style="color: #808080;"></summary></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><param name="expression"></param></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><returns></returns></span>
<span style="color: #0000ff;">private</span> Tuple<Type,<span style="color: #0000ff;">object</span>><span style="color: #000000;"> ProcessArgument(Expression expression)
{
</span><span style="color: #0000ff;">object</span> arg = <span style="color: #0000ff;">default</span>(<span style="color: #0000ff;">object</span><span style="color: #000000;">);
LambdaExpression l </span>=<span style="color: #000000;"> Expression.Lambda(Expression.Convert(expression,expression.Type));
Type parmType </span>=<span style="color: #000000;"> l.ReturnType;
arg </span>=<span style="color: #000000;"> l.Compile().DynamicInvoke();
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> Tuple.Create(parmType,arg);
}</span></pre>
四十三、使用表达式将延迟绑定转换为预先绑定
四十四、尽量减少在公有 API 中使用动态类型
本系列
【博主】反骨仔 【原文】 【GitHub】?可以下载 XMind (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |