Monday, 15 June 2015

c# - How to change a type in an expression tree? -



c# - How to change a type in an expression tree? -

i have method this:

private bool method_1(expression<func<iperson, bool>> expression) { /* code phone call method_2 */ }

in method want alter iperson type type. want phone call method looks this:

private bool method_2(expression<func<persondata, bool>> expression) { /* code */ }

so, in method_1 need alter iperson persondata. how can this?

edit:

when call: method_1(p => p.id == 1) want 'save' status (p.id == 1) want execute status on type, namely iperson. so, need alter look or create new look iperson

edit ii:

for interested, (for now) solution:

private class customexpressionvisitor<t> : expressionvisitor { parameterexpression _parameter; public customexpressionvisitor(parameterexpression parameter) { _parameter = parameter; } protected override look visitparameter(parameterexpression node) { homecoming _parameter; } protected override look visitmember(memberexpression node) { if (node.member.membertype == system.reflection.membertypes.property) { memberexpression memberexpression = null; var membername = node.member.name; var othermember = typeof(t).getproperty(membername); memberexpression = expression.property(visit(node.expression), othermember); homecoming memberexpression; } else { homecoming base.visitmember(node); } } }

and way utilize it:

public virtual bool exists(expression<func<dto, bool>> expression) { var param = expression.parameter(typeof(i)); var result = new customexpressionvisitor<i>(param).visit(expression.body); expression<func<i, bool>> lambda = expression.lambda<func<i, bool>>(result, param); bool exists = _repository.exists(lambda); homecoming exists; }

it easy if utilize .net 4 (update: noted in comment expressionvisitor added in version 4 not 4.5) require googling older frameworks:

there assumptions think valid dto , entity scenario - properties accessed must match.

class persondata { public bool prop { get; set; } } interface iperson { bool prop { get; set; } }

in .net 4 there expressionvisitor class defined makes lot easier if utilize older 1 need write or find implementation of it:

class visitor<t> : expressionvisitor { parameterexpression _parameter; //there must 1 instance of parameter look each parameter //there 1 1 passed here public visitor(parameterexpression parameter) { _parameter = parameter; } //this method replaces original parameter given in constructor protected override look visitparameter(parameterexpression node) { homecoming _parameter; } //this 1 required because persondata not implement iperson , finds //property in persondata same name 1 referenced in look //and declared on iperson protected override look visitmember(memberexpression node) { //only properties allowed if utilize fields need extend // method handle them if (node.member.membertype != system.reflection.membertypes.property) throw new notimplementedexception(); //name of fellow member referenced in original look in //sample id in mine prop var membername = node.member.name; //find property on type t (=persondata) name var othermember = typeof(t).getproperty(membername); //visit left side of look p.id p var inner = visit(node.expression); homecoming expression.property(inner, othermember); } }

proof of concept:

class programme { static void main() { //sample look expression<func<iperson, bool>> look = x => x.prop; //parameter used in generated look var param = expression.parameter(typeof(persondata)); //visiting body of original look gives body of new look var body = new visitor<persondata>(param).visit(expression.body); //generating lambda look form body , parameter //notice need invoke method_2 expression<func<persondata, bool>> lambda = expression.lambda<func<persondata, bool>>(body, param); //compilation , execution of generated method prove works var boolvalue = lambda.compile()(new persondata()); } }

note work simple expressions. if need handle x.prop.prop1 < 3 need extend further.

c# expression-trees

No comments:

Post a Comment