开发者

How do i expand on this expression?

开发者 https://www.devze.com 2023-03-18 06:33 出处:网络
I have this bit of code as an example, basically it spits out p => p.fieldname.StartsWith(\"123\")

I have this bit of code as an example, basically it spits out

p => p.fieldname.StartsWith("123")

But who would i expand on this to do something like this:

p => p.anotherentity.fieldname.StartsWith("123")

Here is a sample of the code i am have refactored for own needs:

string propertyName = "FirstName";
string methodName = "StartsWith";
string keyword = "123";

Type t = typeof (Person);

ParameterExpression paramExp = Expression.Parameter(t, "p");
// the parameter: p

MemberExpression memberExp = Expression.MakeMemberAccess(paramExp,
                                                         t.GetMember(propertyName).FirstOrDefault());
// part of the body: p.FirstName

MethodCallExpression callExp = Expression.Call(memberExp,
                                               typeof (string).GetMethod(methodName,
                                                                         new Type[] {typeof (string)}),
                                               Expression.Constant(keyword));
// the body: p.FirstName.Star开发者_如何学CtsWith("123")

Expression<Func<Person, bool>> whereExp = Expression.Lambda<Func<Person, bool>>(callExp, paramExp);
Expression<Func<Person, string>> selectExp = Expression.Lambda<Func<Person, string>>(memberExp, paramExp);

Console.WriteLine(whereExp); // p => p.FirstName.StartsWith("123")
Console.WriteLine(selectExp); // p => p.FirstName

To further explain let me show you what i would like to do:

public class Person 
{
    public string IdentityCode {get;set;}
    public Loans Loans {get;set;}
}

public class Loans 
{
  public int Id {get;set;}
  public Asset Assets {get;set;}
  public Person person {get;set;}
}

public class Asset  
{
  public string SerialNumber {get;set;}
}

Then using an expression build something like this:

p => p.Loans.Asset.SerialNumber.StartsWith("123)

Or

p => p.Loans.Person.IdentityCode.StartsWith("123")


untested, but...

ParameterExpression paramExp = Expression.Parameter(t, "p"); // the parameter: p

MemberExpression memberExp = 
    Expression.MakeMemberAccess(paramExp, t.GetMember(propertyName).FirstOrDefault());

would become something like:

ParameterExpression paramExp = Expression.Parameter(t, "p"); // the parameter: p

MemberExpression otherEntityExp = 
    Expression.MakeMemberAccess(paramExp, t.GetMember("anotherentity").FirstOrDefault());

MemberExpression memberExp = 
    Expression.MakeMemberAccess(otherEntityExp, t.GetMember(propertyName).FirstOrDefault());


I'm not sure what you're asking for, updating an expression or building one from scratch...

If you already have the existing, old expression and want to update it, it would be very easy to create a new one. The idea is to dig through the expression tree down to the expression you want to replace. Then update all parent expressions with the newly replaced one.

Expression<Func<Obj, bool>> expr = p => p.fieldname.StartsWith("123");
var body = expr.Body as MethodCallExpression;   // *.StartsWith()
var obj = body.Object as MemberExpression;      // p.fieldname
var param = expr.Parameters.First();            // p
var newAccess = Expression.PropertyOrField(param, "anotherentity"); // p.anotherentity
var newObj = obj.Update(newAccess);                 // update obj
var newBody = body.Update(newObj, body.Arguments);  // update body
var newExpr = expr.Update(newBody, expr.Parameters);// update expr

Otherwise to build up the expression tree:

Expression<Func<Person, bool>> expr =
    p => p.Loans.Asset.SerialNumber.StartsWith("123");

Work it out from the beginning.

var p = Expression.Parameter(typeof(Person), "p");
var accessLoans = Expression.PropertyOrField(p, "Loans");
var accessAsset = Expression.PropertyOrField(accessLoans, "Asset");
var accessSerialNumber = Expression.PropertyOrField(accessAsset, "SerialNumber");
var callArgs = new Expression[] { Expression.Constant("123", typeof(string)) };
var callStartsWith = Expression.Call(accessSerialNumber, "StartsWith", null, callArgs);
var newExpr = Expression.Lambda<Func<Person, bool>>(callStartsWith, p);

I'll leave the last one as an exercise for you.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号