lambda表达式的解析(七) 对象的创建
来源:互联网 发布:河南省大数据 编辑:程序博客网 时间:2024/06/05 20:58
C#里用来创建对象的方式有以下几种
调用构造函数 new obj(...)
初始化成员列表 new obj { f1 = xxx, f2 = xxx, ... }
创建数组 new arraytype[] { e1, e2, e3, ...}
如果是匿名对象话,创建方式只有后2种。
非匿名对象的创建:
private Expression ProcessNewExpression(ParseTreeNode expNode) { var typeName = expNode.GetChild("qual_name_with_targs").FindTokenAndGetText(); var args = expNode.GetChild("creation_args").GetDescendant("argument_list"); var arglist = new List<Expression>(); if (args != null) { foreach (var arg in args.ChildNodes) { arglist.Add(ProcessExpression(arg.FirstChild)); } } var type = GetType(typeName); if (expNode.GetChild("creation_args").HasChild("array_creation_args")) { var elements = expNode.GetChild("array_initializer_opt").GetDescendant("elem_initializer_list"); var elemlist = new List<Expression>(); if (elements != null) { foreach (var child in elements.ChildNodes) { elemlist.Add(ProcessExpression(child.GetChild("initializer_value").FirstChild)); } } return Expression.NewArrayInit(type, elemlist); } var newexp = Expression.New(type.GetConstructor(arglist.Select(e => e.Type).ToArray()), arglist); var members = expNode.GetChild("array_initializer_opt").GetDescendant("elem_initializer_list"); var bindlist = new List<MemberBinding>(); if (members != null) { foreach (var child in members.ChildNodes) { var memberName = child.GetChild("Identifier").GetValue(); var expr = ProcessExpression(child.GetChild("initializer_value").FirstChild); bindlist.Add(Expression.Bind(type.GetMember(memberName).First(), expr)); } } return Expression.MemberInit(newexp, bindlist); }
大致过程就是先获得创建对象的类型,然后分析是否有调用构造方法并获取构造参数列表,如是创建数组对象则获取元素列表并返回数组初始化表达式,最后就是如果有成员初始化列表就和new表达式一起使用。
匿名类型创建:
private Expression ProcessNewAnonymousExpression(ParseTreeNode expNode) { if (expNode.HasChild("anonymous_array_creation_expression")) { var elements = expNode.GetDescendant("element_declarator_list"); var elemlist = new List<Expression>(); var elemtype = typeof(void); if (elements != null) { foreach (var child in elements.ChildNodes) { var exp = ProcessExpression(child.FirstChild); elemtype = exp.Type; elemlist.Add(exp); } } return Expression.NewArrayInit(elemtype, elemlist); } var members = expNode.GetDescendant("member_declarator_list"); var memblist = new List<Expression>(); var names = new List<string>(); var types = new List<Type>(); List<AnonymousMetaProperty> properties = new List<AnonymousMetaProperty>(); if (members != null) { foreach (var child in members.ChildNodes) { var name = child.GetChild("Identifier").GetValue(); var expr = ProcessExpression(child.GetChild("primary_expression")); names.Add(name); types.Add(expr.Type); memblist.Add(expr); } } return GetAnonymousExpression(names.ToArray(), types.ToArray(), memblist.ToArray()); }
创建匿名表达式最大的问题是需要对匿名类型进行引用,也就是说需要在解析的时候动态创建匿名类型,在项目里使用了InterLinq创建匿名类型部分的代码(InterLinq是一个提供远程执行LINQ方法的框架)来创建一个匿名类型:
private static Type GetAnonymousType(string[] propertyNames, Type[] propertyTypes) { List<AnonymousMetaProperty> properties = new List<AnonymousMetaProperty>(); for (int i = 0; i < propertyNames.Length; ++i) { properties.Add(new AnonymousMetaProperty(propertyNames[i], propertyTypes[i])); } return AnonymousTypeHelper.GetAnonymousType(properties.ToArray()).GetClrType(); } private Expression GetAnonymousExpression(IEnumerable<string> names, IEnumerable<Type> types, IEnumerable<Expression> membs) { var newobj = GetAnonymousType(names.ToArray(), types.ToArray()); return Expression.New(newobj.GetConstructor(types.ToArray()), membs, newobj.GetProperties()); }
不过匿名数组可以根据初始化参数确定数组元素类型所以无需创建匿名类型这个过程。
至此大部分的表达式都能被顺利解析转换了,用Irony对lambda表达式解析的介绍就告一段落了,对typeof、泛型调用以及BlockExpression等的支持和grammar的进一步完善留着下次再介绍了。
- lambda表达式的解析(七) 对象的创建
- lambda表达式的解析(一) 序
- 对lambda表达式的解析(一)
- 对lambda表达式的解析(二)
- lambda表达式的解析(二) 常量表达式
- lambda表达式的解析(三) 类型转换表达式
- lambda表达式的解析(四) 运算符表达式
- lambda表达式的解析(六) 成员访问表达式
- lambda表达式的解析(五) Lambda表达式与闭包类型
- 动态创建Lambda 表达式的例子!
- 使用lambda表达式的方式创建监听器
- List排序问题:根据list对象的创建时间排序,后用lambda表达式
- VS2010的Lambda表达式
- C#的Lambda表达式
- C++的lambda表达式
- Lambda表达式的使用
- Lambda 表达式的构成
- newlisp的lambda表达式
- 抽象类和接口的使用场合
- android-简单的intent传值
- 如何创建Oracle DBLink
- jsp,web开发的在线考试系统
- Jmail发送邮件
- lambda表达式的解析(七) 对象的创建
- oracle 字符串操作
- 脏读、不可重复读 共享锁、悲观锁 和 事务五种隔离级别
- Spring注入的几种形式
- Nokia Java 开发(二)—— 创建第一个程序
- Nginx语法高亮
- 【转】一位软件工程师的6年总结
- android-IntentFliter
- zoj 2164 Hanafuda Shuffle