Как мне расширить это выражение? - PullRequest
1 голос
/ 09 июля 2011

У меня в качестве примера этот бит кода, в основном он выплевывает

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

Но кого бы я расширил, чтобы сделать что-то вроде этого:

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

Вот пример кода, который я реорганизовал для собственных нужд:

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.StartsWith("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

Для дальнейшего объяснения позвольте мне показать вам, что я хотел бы сделать:

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;}
}

Затем с помощью выражения создайте что-то вроде этого:

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

Или

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

Ответы [ 2 ]

2 голосов
/ 09 июля 2011

не проверено, но ...

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

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

станет что-то вроде:

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());
0 голосов
/ 10 июля 2011

Я не уверен, что вы просите, обновить выражение или создать его с нуля ...

Если у вас уже есть существующее старое выражение и вы хотите обновить его, было бы очень легко создать новое. Идея состоит в том, чтобы копаться в дереве выражений до выражения, которое вы хотите заменить. Затем обновите все родительские выражения с помощью недавно замененного.

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

В противном случае для построения дерева выражений:

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

Работай с самого начала.

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);

Я оставлю последнее упражнение для вас.

...