前言
关于”读行者“
俗语有云:"读万卷书,行万里路“。多读一些优秀代码,不仅可以锻炼我们读代码的能力(便于维护或相互交流),还可以吸取很多我们成长所需的知识点。多读,才能开阔我们的眼界,才能在我们小有所成沾沾自喜时提醒我们:前面的路还很长。
回首自己成长之路,从C#入门后,就一直在CodeProject上阅读。阅读对于我们能力提高的重要性,我是深有体会的。(此帐号注册很久了,也没做过什么贡献,惭愧)
阅读是一种探索式的学习,你可以针对demo中的知识点有选择的研究;如果我们阅读的是一个project,还可以断点调试,更改前后条件,验证自己对API的猜想和加深理解。这些都比直接查阅API文档和看书效果好很多。另外,如果觉得对自己有帮助和启发的代码,还可以存下来,作为自己的积累,供今后查阅和调用。
如果有时间,我将不定期分享一些读书笔记,放在此类别下。如果有兴趣,不妨一起”读“吧。
Demo 地址: Fluent Method and Type Builder(自己下载)
研究目的: 进阶学习Linq.Expression和System.Reflection和System.Reflection.Emit。 同时这个工具在动态创建方法和类型时(如AOP),也十分有用。
点1:为什么方法中:
string fileName = null; var method = new FluentMethodBuilder(typeof(void)). AddParameter(() => fileName).
的表达式“() => fileName”, 在AddParameter中访问时,表达式的类型是MemberExpression并且 Expression.Member.MemberType=MemberType.Field? 'fileName'明明是一个局部变量呀?
答案:见StackOverFlow
class C { void M() { int x = 1; Func<int, int> f = y=>x+y; } }
实际上被编译成了:
class C
{
private class DisplayClass
{
public int x;
public int AnonymousMethod(int y)
{
return this.x + y;
}
}
void M()
{
C.DisplayClass d = new C.DisplayClass();
d.x = 1;
Func<int, int> f = d.AnonymousMethod;
}
}
点2: MemberExpression的基本属性:MSDN
Member: 获取表达式指向的属性或字段 [和System.Reflection第一次交互,返回类型为System.Reflection.MemberInfo]
Expression: 获取包含表达式指向的属性或字段的object
Type: 表达式里的委托的类型
NodeType: 对表达式的类型的细分,在二元操作表达式时需要用到以细分为加,减等。
断点调试中发现:
Expression: ()=>xxx.fileName NodeType是 Lambda
Expression.Body xxx.fileName NodeType是MemberAccess
Body.Expression xxx NodeType是Constant
((ConstantExpression)Body.Expression).Value可以访问xxx对象,通过watch窗口,可以查看这个匿名类的属性,证明1中的结论)
点3: ParameterExpression
IsByRef: 是否是引用类型
Name: 参数名称
产生: Expression.Parameter(fieldType, fieldName)或 Expression.Variable(fieldType, fieldName)
额外学习点:
a.生成ref参数类型: fieldType = fieldType.MakeByRefType();
b.装箱类型: fieldType = typeof(Box<>).MakeGenericType(fieldType); (联想typeof(Nullable<>).MakeGenericType)。(如果是要从泛型类型”Box<x>“中获取Box<>类型呢?其实代码中有)
点4: Using的实现
var result = Expression.Block ( new ParameterExpression[]{otherVariable}, Expression.Assign(otherVariable, _usingValue), Expression.Assign(_usingVariable, otherVariable), Expression.TryFinally ( base._CompileToExpression(), Expression.IfThen ( Expression.NotEqual(otherVariable, Expression.Constant(null)), Expression.Block ( Expression.Assign(_usingVariable, Expression.Constant(null, _usingVariable.Type)), Expression.Call(otherVariable, _disposeMethod) ) ) ) );
可以看见Using语句的实现,在LinqExpression中本质上使用的是TryFinally(expBody,expFinally)。
额外知识点:
a. Expression可以把语句组装起来一起执行;
b. 赋值操作和If语句的实现: Expression.Assign和Expression.IfThen。 Demo中_usingValue的类型为MemberAccess, 即xxx.StreamReader;
c. 和System.Reflection的第二次交互: Expression.Call(varableExp, methodInfo)。
点5: 循环语句的实现
var innerBody = base._CompileToExpression(); var result = Expression.Block ( Expression.Label(ContinueTarget), innerBody, Expression.Goto(ContinueTarget), Expression.Label(BreakTarget) ); return result;
可以发现,循环语句本年是通过GoTo实现的,在循环体的入口和出口创建两个Label, 执行完后让程序跳转到循环体的入口;如果执行过程中要中断程序,刚跳转至循环语句的出口。
那么,在innerBody中,必然有跳转到Break处的语句,这可以从Break()方法看到:
_IBlockBuilder instance = this; while(instance != null) { _ILoop loop = instance as _ILoop; if (loop != null) { var gotoExpression = Expression.Goto(loop.BreakTarget); var statement = new _Expression(gotoExpression); _statements.Add(statement); return _this; } instance = instance.Parent as _IBlockBuilder; }
其流程也需要注意一下: 从当前的Block级语句中逐级往上遍历,利用Goto BreakTarget中断离当前块最近的一级Loop循环。
点6: Expression Visitor
在FluentMethodBuilder的372行有这样一句:
body = _visitor.Visit(body);
大致看下其中的代码,尤其是VisitMember方法,好像就是在根据节点在上下文中找对应的表达式。不要它行不行?肯定不行,否则作者不会写它。
那么它到底是干啥的呢?
先把它注了看看:再F5,会报一个错误,差不多是说streamreader的参数path不能为null。好像是赋的值没有传过去,但具体这又是为什么呢?
取消先前的注释,打个断点在"visit"语句之前和之后,查看一下body的DebugView,对比一下可以发现(以第5行代码为例):
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" alt="" width="417" height="155" data-ke-src="data:image/png;base64,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" />
//visit之前 $var1 = .New System.IO.StreamReader(.Constant<TypeBuildingSample.Program+<>c__DisplayClass0>(TypeBuildingSample.Program+<>c__DisplayClass0).fileName) //visit之后 $var1 = .New System.IO.StreamReader($fileName);
这就是为什么不被visit,执行method时会报参数为null的错误的元凶了。因为之前使用的仍然是匿名类的fileName字段,而非我们传进去的参数!
再想想之前的代码:Using(() => streamReader, () => new StreamReader(fileName)),把局部变量传给了StreamReader作参数,不visit当然会出现那样的语句。
那么不使用局部变量呢?也不行,因为我们在一个方法的外部无法访问它自身的局部变量,所以作者先以上级方法的局部变量代替之,然后再把用Visitor把它恢复为“真正的局部变量”,不用再依赖上级方法中的局部变量而存在了。
所以ExpressionVisitor到底是干啥的,从这里可以看出:它可以遍历和修改Linq Expression中的子元素(语法树的子节点)。
点7: 连缀写法的实现及整体实现
首先是设计模式,整体使用组合模式, 产生树状体系。子节点实现了ICompile接口,每生成一个新的节点,都会添加到父级节点的statements中,最终遍历至根结点,生成总的 statements。如果我们正向划分也会发现:一个类可以划分为属性,方法,字段,事件的代码等,方法的代码又可以划分为循环块,条件块,using 块等,这些块又可以相互嵌套。。。
连缀写法的实现是通过EndXXX()方法实现的,通过此方法将子节点的上级节点返回,这样可以继续调用父级节点的成员而不必中断语句。