利用Lambda表达式: 重构代码时自动更新反射成员。
来源:互联网 发布:软件快速开发平台 编辑:程序博客网 时间:2024/06/02 05:26
在CSDN 上 看了一篇Daniel Cazzulinode的文章:Linq的超越
(原文链接http://blog.csdn.net/programmer_editor/archive/2006/09/29/1305859.aspx)
挺有意思的,自己也研究了一下.
题目可能没有说清楚,那么咱么现在考虑一个场景:
为了能够显示不同数据对象的数据,提高可复用性,你写了一个继承自DataGridView的控件,里面有一个Load()的公共方法,用来载入数据。
propertyNames 是一组要显示数据的属性名
headerText 是对应的Column的headerText
在Load()方法中,遍历items的每一个元素。并且用反射的方法,获取指定属性名的数据,显示在DataGridView里。
例如我们要显示一组人的姓名和年龄:
假如我们以后认为Name这个属性名并不好,并且想用NickName替代,利用VS强大的功能,很容易就可以完成重构,但是问题来了,我们还要手动去更改Load()调用的参数,因为我们传入的是固定的字符串,VS并不会自动的帮助我们进行更改。
在Lambda引入之前,我们是没有办法完成这个功能的,但是现在我们利用Lambda Expression便可以实现。
首先,设计一个类
下面这个方法是关键,我们传入一个Lambda表达式,她将返回一个MemberInfo,只是这个表达式是有要求的,她的形式是 "参数 => 成员调用"。
由于返回的是MemberInfo,是PropertyInfo,MethodInfo等的基类。而事实上,如果我们的"成员调用"是一个Property那么此方法实际上返回的就是一个PropertyInfo,我们只要将它转化一下就可以了。
下面是测试结果:
细心的你也许已经发现,其实我们传入的Lambda表达式并没有真正的被编译并且执行。所以假如我们要传入 "p=>p.someMethod(.....)" 而someMethod这个方法是有参数的,那么我们只需简单的传入一个 null 就可以了,就像这样"p=>p.someMethod(null,null...)" 。
至于GetMemberInfo<T>(..)方法为什么要那么实现,就留给读者自己动手试一下吧,只要在Debug状态下查看一下Expression的结构,自然就明白了。
(原文链接http://blog.csdn.net/programmer_editor/archive/2006/09/29/1305859.aspx)
挺有意思的,自己也研究了一下.
题目可能没有说清楚,那么咱么现在考虑一个场景:
为了能够显示不同数据对象的数据,提高可复用性,你写了一个继承自DataGridView的控件,里面有一个Load()的公共方法,用来载入数据。
public void LoadData(object[] items,string[] propertyNames,string[] headerText)
items 是某一个类型的对象数组。propertyNames 是一组要显示数据的属性名
headerText 是对应的Column的headerText
在Load()方法中,遍历items的每一个元素。并且用反射的方法,获取指定属性名的数据,显示在DataGridView里。
例如我们要显示一组人的姓名和年龄:
Load(Persons,
newstring[] {"Name","Age" },
newstring[] {"姓名","年龄" });)
newstring[] {"Name","Age" },
newstring[] {"姓名","年龄" });)
假如我们以后认为Name这个属性名并不好,并且想用NickName替代,利用VS强大的功能,很容易就可以完成重构,但是问题来了,我们还要手动去更改Load()调用的参数,因为我们传入的是固定的字符串,VS并不会自动的帮助我们进行更改。
在Lambda引入之前,我们是没有办法完成这个功能的,但是现在我们利用Lambda Expression便可以实现。
首先,设计一个类
public class TestClass
{
public string Name;
public string PName {set; get; }
public string GetName()
{
return Name;
}
public int Age;
public int PAge {set; get; }
public int GetAge()
{
return Age;
}
public TestClass GetInstance()
{
return new TestClass();
}
}
{
public string Name;
public string PName {set; get; }
public string GetName()
{
return Name;
}
public int Age;
public int PAge {set; get; }
public int GetAge()
{
return Age;
}
public TestClass GetInstance()
{
return new TestClass();
}
}
下面这个方法是关键,我们传入一个Lambda表达式,她将返回一个MemberInfo,只是这个表达式是有要求的,她的形式是 "参数 => 成员调用"。
由于返回的是MemberInfo,是PropertyInfo,MethodInfo等的基类。而事实上,如果我们的"成员调用"是一个Property那么此方法实际上返回的就是一个PropertyInfo,我们只要将它转化一下就可以了。
public static MemberInfo GetMemberInfo<T>(Expression<Func<T,object>> exp)
{
Expression texp= exp.Body;
if (texp.NodeType== ExpressionType.Convert)
texp= ((UnaryExpression)texp).Operand;
if (texp.NodeType== ExpressionType.Call)
return ((MethodCallExpression)texp).Method;
if (texp.NodeType== ExpressionType.MemberAccess)
return ((MemberExpression)texp).Member;
return null;
}
来做一个测试{
Expression texp= exp.Body;
if (texp.NodeType== ExpressionType.Convert)
texp= ((UnaryExpression)texp).Operand;
if (texp.NodeType== ExpressionType.Call)
return ((MethodCallExpression)texp).Method;
if (texp.NodeType== ExpressionType.MemberAccess)
return ((MemberExpression)texp).Member;
return null;
}
static void Main(string[] args)
{
Console.WriteLine(GetMemberInfo<TestClass>(p=> p.Age).Name);
Console.WriteLine(GetMemberInfo<TestClass>(p=> p.PAge).Name);
Console.WriteLine(GetMemberInfo<TestClass>(p=> p.GetAge()).Name);
Console.WriteLine(GetMemberInfo<TestClass>(p=> p.Name).Name);
Console.WriteLine(GetMemberInfo<TestClass>(p=> p.PName).Name);
Console.WriteLine(GetMemberInfo<TestClass>(p=> p.GetName()).Name);
Console.WriteLine(GetMemberInfo<TestClass>(p=> p.GetInstance()).Name);
}
{
Console.WriteLine(GetMemberInfo<TestClass>(p=> p.Age).Name);
Console.WriteLine(GetMemberInfo<TestClass>(p=> p.PAge).Name);
Console.WriteLine(GetMemberInfo<TestClass>(p=> p.GetAge()).Name);
Console.WriteLine(GetMemberInfo<TestClass>(p=> p.Name).Name);
Console.WriteLine(GetMemberInfo<TestClass>(p=> p.PName).Name);
Console.WriteLine(GetMemberInfo<TestClass>(p=> p.GetName()).Name);
Console.WriteLine(GetMemberInfo<TestClass>(p=> p.GetInstance()).Name);
}
下面是测试结果:
细心的你也许已经发现,其实我们传入的Lambda表达式并没有真正的被编译并且执行。所以假如我们要传入 "p=>p.someMethod(.....)" 而someMethod这个方法是有参数的,那么我们只需简单的传入一个 null 就可以了,就像这样"p=>p.someMethod(null,null...)" 。
至于GetMemberInfo<T>(..)方法为什么要那么实现,就留给读者自己动手试一下吧,只要在Debug状态下查看一下Expression的结构,自然就明白了。
- 利用Lambda表达式: 重构代码时自动更新反射成员。
- 使用Lambda表达式重构委托
- 利用crontab 自动更新svn代码
- lambda表达式和利用lambda排序
- Lambda表达式与简洁代码
- 利用coding.net的webhook自动更新代码
- 【经典实例】利用C#反射动态编译代码,创建类的实例,并调用其成员
- lambda表达式的解析(六) 成员访问表达式
- 利用Eclipse进行代码重构
- 利用Lambda表达式简化命令者模式
- 重构代码-简化条件表达式
- 代码重构(四):条件表达式重构规则
- 代码重构(四):条件表达式重构规则
- 利用反射动态调用类成员
- (C#)利用反射动态调用类成员
- 利用反射访问类的私有成员
- 利用Java反射机制获得私有成员
- C#利用反射动态调用类成员
- 后台弹出js
- SQL Server CLR全功略之三---CLR标量函数、表值函数和聚合函数(UDA)
- hadoop datanode源码分析
- 文字符号设计方法整理1--笔画字形(体)处理方法
- 不同的时期该如何找对销售人员?
- 利用Lambda表达式: 重构代码时自动更新反射成员。
- 事件(一)——三种事件模型
- 善用GridView控件的HyperLinkField数据行
- C++标准转换运算符const_cast
- 如何让HyperLinkField的链接带多个参数
- cocos2d-x 编译 经验&& bug
- 事件(二)——Jquery事件模型
- 字符过滤(2013华为校园招聘上机考试)
- Hadoop RPC源码分析