I read an article about Daniel cazzulinode on csdn. Article : The transcendence of LINQ
(Original link http://blog.csdn.net/programmer_editor/archive/2006/09/29/1305859.aspx)
Very interesting. I also studied it myself.
The question may not be clearly stated, so we now consider a scenario:
To display data of different data objects and improve reusability, you have written a control inherited from the datagridview dview, which contains a public load () method to load data.Public VoidLoaddata (Object[] Items,String[] Propertynames,String[] Headertext)
Items is an array of objects of a certain type.
Propertynames is a set of attribute names for displaying data.
Headertext is the headertext of the corresponding column.
In the load () method, traverse every element of items. In addition, the data of the specified attribute name is obtained using the reflection method and displayed in the datagridview.
For example, we want to display the name and age of a group of people: Load (persons,
New String [] {"Name","Age"} ,
New String [] {"Name","Age"} );)
If we think that the name attribute name is not good in the future and want to replace it with nickname, we can easily reconstruct it using the powerful functions of Vs, but the problem arises, we also need to manually change the parameters called by load (), because we pass in a fixed string, Vs will not automatically help us to make changes.
Before Lambda was introduced, we had no way to complete this function, but now we can implement it using Lambda expression.
First, design a class Public Class Testclass
{
Public String Name;
Public String Pname {Set;Get;}
Public String Getname ()
{
ReturnName;
}
Public Int Age;
Public Int Page {Set;Get;}
Public Int Getage ()
{
ReturnAge;
}
Public Testclass getinstance ()
{
Return NewTestclass ();
}
}
The following method is the key. When we pass in a Lambda expression, she will return a memberinfo, but this expression is required. Its form is "parameter => member call ".
Because memberinfo is returned, it is a base class such as propertyinfo and methodinfo. In fact, if our "member call" is a property, this method actually returns a propertyinfo, and we only need to convert it.
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 ;
}
Perform a test 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 );
}
The test result is as follows:
You may have noticed that the lambda expressions we pass in are not actually compiled and executed. So if we want to input "P => P. somemethod (.....) "The somemethod method has parameters, so we only need to input a null value, just like this" P => P. somemethod (null, null ...) ".
As for the implementation of the getmemberinfo <t> (...) method, you can leave it to the reader to give it a try. You only need to check the expression structure in the debug state, and you will naturally understand it.