How to create expression tree / lambda for a deep property from a string?

Something like: setProperyValue(obj, propertyName, value) { head, tail = propertyName. SplitByDotToHeadAndTail(); // Person.Address. Postcode => {head=Person, tail=Address.

Postcode} if(tail. Length == 0) setPropertyValueUsingReflection(obj, head, value); else setPropertyValue(getPropertyValueUsingReflection(obj, head), tail, value); // recursion }.

I always try to over engineer things. Keep it simple! Ill try that, ta – Andrew Bullock Feb 11 '09 at 14:41.

It sounds like you're sorted with regular reflection, but for info, the code to build an expression for nested properties would be very similar to this order-by code. Note that to set a value, you need to use GetSetMethod() on the property and invoke that - there is no inbuilt expression for assigning values after construction (although it is supported in 4.0). (edit) like so: using System; using System.

Linq; using System.Linq. Expressions; using System. Reflection; class Foo { public Foo() { Bar = new Bar(); } public Bar Bar { get; private set; } } class Bar { public string Name {get;set;} } static class Program { static void Main() { Foo foo = new Foo(); var setValue = BuildSet("Bar.Name"); var getValue = BuildGet("Bar.

Name"); setValue(foo, "abc"); Console. WriteLine(getValue(foo)); } static Action BuildSet(string property) { string props = property. Split('.

'); Type type = typeof(T); ParameterExpression arg = Expression. Parameter(type, "x"); ParameterExpression valArg = Expression. Parameter(typeof(TValue), "val"); Expression expr = arg; foreach (string prop in props.

Take(props. Length - 1)) { // use reflection (not ComponentModel) to mirror LINQ PropertyInfo pi = type. GetProperty(prop); expr = Expression.

Property(expr, pi); type = pi. PropertyType; } // final property set... PropertyInfo finalProp = type. GetProperty(props.Last()); MethodInfo setter = finalProp.GetSetMethod(); expr = Expression.

Call(expr, setter, valArg); return Expression. Lambda(expr, arg, valArg).Compile(); } static Func BuildGet(string property) { string props = property. Split('.

'); Type type = typeof(T); ParameterExpression arg = Expression. Parameter(type, "x"); Expression expr = arg; foreach (string prop in props) { // use reflection (not ComponentModel) to mirror LINQ PropertyInfo pi = type. GetProperty(prop); expr = Expression.

Property(expr, pi); type = pi. PropertyType; } return Expression. Lambda(expr, arg).Compile(); } }.

Just been searching on a similar topic and this came up first on google, and answered my question :D – Andrew Bullock Mar 6 '09 at 17:00.

You want to look at providing your own PropertyDescriptor's via TypeConverter or some other source. I have implemented exactly what you describe for current project (sorry, commercial, else I would share), by deriving from BindingSource, and providing the information via there. The idea is as follows: All you need to do is, once you have the type is to create little 'stacks' for the getter and setters of properties, and those you can collect via walking the property tree of the type and its properties breadth first, limiting the depths to a specified number of levels and removing circular references depending on your data structures.

I am using this quite successfully with Linq2SQL objects and in combination with their binding lists :).

Expression Tree #include struct tree { char info; struct tree *rchild; struct tree *lchild; }; int prec(char data); typedef struct tree * node; char pop_op(); node pop_num(); void push_op(char item); node create() { return((node)malloc(sizeof(node))); } node num20,root=NULL; char op20,oprt,ev20; int nt=-1,ot=-1,et=-1; main() { node newnode,item,temp; char str50; int i,k,p,s,flag=0; printf("ENTER THE EXPRESSION "); scanf("%s",str); printf("\n%s",str); for(i=0;stri! ='\0';i++) { if(isalnum(stri)) { newnode=create(); newnode->info=stri; newnode->lchild=NULL; newnode->rchild=NULL; item=newnode; push_num(item); } else { if(ot! =-1) p=prec(opot); else p=0; k=prec(stri); if(k==5) { while(k!

=1) { oprt=pop_op(); newnode=create(); newnode->info=oprt; newnode->rchild=pop_num(); newnode->lchild=pop_num(); // if(root==NULL) root=newnode; // else if((newnode->rchild==root)||(newnode->lchild==root)) // root=newnode; push_num(root); k=prec(opot); } oprt=pop_op(); } else if(k==1) push_op(stri); else { if(k>p) push_op(stri); else { if(krchild=pop_num(); newnode->lchild=pop_num(); if(root==NULL) root=newnode; else if((newnode->rchild==root)||(newnode->lchild==root)) root=newnode; push_num(newnode); push_op(stri); // k=prec(opot); } } } } } printf("\nThe prefix expression is\n "); preorder(root); printf("\nThe infix exp is\n "); inorder(root); printf("\nThe postfix expression is\n "); postorder(root); evaluate(); } void push_op(char item) { op++ot=item; } push_num(node item) { num++nt=item; } char pop_op() { if(ot! =-1) return(opot--); else return(0); } node pop_num() { if(nt! =-1) return(numnt--); else return(NULL); } int prec(char data) { switch(data) { case '(':return(1); break; case '+': case '-':return(2); break; case '*': case '/':return(3); break; case '^':return(4); break; case ')':return(5); break; } } inorder(node temp) { if(temp!

=NULL) { inorder(temp->lchild); printf("%c ",temp->info); inorder(temp->rchild); } } preorder(node temp) { if(temp! =NULL) { printf("%c ",temp->info); preorder(temp->lchild); preorder(temp->rchild); } } postorder(node temp) { if(temp! =NULL) { postorder(temp->lchild); postorder(temp->rchild); printf("%c ",temp->info); ev++et=temp->info; } } evaluate() { int i,j=-1,a,b,ch20; for(i=0;evi!

='\0';i++) { if(isalnum(evi)) ch++j=evi-48; else { b=chj; a=chj-1; switch(evi) { case '+':ch--j=a+b; break; case '-':ch--j=a-b; break; case '*':ch--j=a*b; break; case '/':ch--j=a/b; break; } } } printf("\nValue = %d",ch0); }.

String props = property. ParameterExpression arg = Expression. ParameterExpression valArg = Expression.

Foreach (string prop in props. PropertyInfo pi = type. Expr = Expression.

Type = pi. PropertyInfo finalProp = type. Expr = Expression.

String props = property. ParameterExpression arg = Expression. PropertyInfo pi = type.

Expr = Expression. Type = pi.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions