1

UPDATE:

I'll try to explain what I mean. There are 2 different classes (MyClass1 and MyClass2) and method to convert class1 to class2:

class MyClass1
  {
        //...Some fields and properties
 }

  class MyClass2
   {
        //...Some fields and properties
  }

public MyClass2 Convert(MyClass1 class1)
{
//.....
return class2Object;
}

There are 2 different methods:

   void method1(Expression<Func<MyClass1, bool>> where, //other parameters)
    {
        //some operations
        //...............

        //need to call method2(Expression<Func<MyClass2, bool>>)
        //   BUT! How do I convert Expression<Func<MyClass1, bool>> 
        //   to Expression<Func<MyClass2, bool>>
    }

    void method2(Expression<Func<MyClass2, bool>> where, //other parameters)
    {
        //some operations
    }

How do I convert Expression< Func< MyClass1, bool>> to Expression< Func< MyClass2, bool > >

7
  • 1
    Since MyClass1 and MyClass2 cannot be converted into each other, how do you expect to convert the delegate? Commented Feb 27, 2011 at 12:08
  • 1
    Until you define explicit conversions between MyClass1 and MyClass2 you can't even get started. Commented Feb 27, 2011 at 12:09
  • Your edit still doesn't say how to convert between the two. Commented Feb 27, 2011 at 12:17
  • It doesn't matter how to convert MyClass1 to MyClass2 . Just use a method ConvertFromClass1ToClass2(). Commented Feb 27, 2011 at 12:22
  • 1
    Very rarely do I find anything that doesn't matter. The question is unanswerable without giving extended thought to your model, and any proposal could be far from scope of this question. Please elaborate. Commented Feb 27, 2011 at 12:33

4 Answers 4

7

Let me guess what you are asking: Your MyClass1 and MyClass2 look the same (they both have an int field1 and a string field2). Now you have an Expression<Func<MyClass1,bool>>, something like:

Expression<Func<MyClass1, bool>> exp1 = x => x.field1 == 100; // x is MyClass1

And you want another expression, which looks the same, but it's for MyClass2:

Expression<Func<MyClass2, bool>> exp2 = x => x.field1 == 100; // x is MyClass2

If this is what you are asking, here is my answer:

To get the expression for MyClass2, you need to replace all x in exp1, because all x in exp1 are of type MyClass1. ExpressionVisitor is exactly what you want.

class MyExpressionVisitor : ExpressionVisitor
{
    public ParameterExpression NewParameterExp { get; private set; }

    public MyExpressionVisitor(ParameterExpression newParameterExp)
    {
        NewParameterExp = newParameterExp;
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        return NewParameterExp;
    }

    protected override Expression VisitMember(MemberExpression node)
    {
        if (node.Member.DeclaringType == typeof(MyClass1))
            return Expression.MakeMemberAccess(this.Visit(node.Expression), 
               typeof(MyClass2).GetMember(node.Member.Name).FirstOrDefault());
        return base.VisitMember(node);
    }
}

The visitor will go through(say "visit") the whole expression, visit all the nodes. When it comes to an ParameterExpression node, we change the node (because it's MyClass1, we change it to MyClass2, see VisitParameter method). Another thing we need to change is, when the visitor comes to a node like x.field1, it's visiting the field1 in MyClass1, we need to modify it too(see VisitMember). After going through the whole exp1, we get a totally new exp2, with some nodes replaced, that's what we want.

Expression<Func<MyClass1, bool>> exp1 = x => x.field1 == 100;

var visitor = new MyExpressionVisitor(Expression.Parameter(typeof(MyClass2), 
                        exp1.Parameters[0].Name));

var exp2 = Expression.Lambda<Func<MyClass2, bool>>
                (visitor.Visit(exp1.Body), visitor.NewParameterExp);

//the following is for testing
var data = new MyClass2();
Console.WriteLine(exp2.Compile()(data));  //False
data.field1 = 100;
Console.WriteLine(exp2.Compile()(data));   //True
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for answer, but it's something other than what I mean.
@Alex then how about describing what you mean?
@Alex: Can you give an example of the Expression?
1

Expression trees are immutable, so to do this ou would need to walk the entire tree, rebuilding it and substiting any uses of the type with the equivalent - usually by writing a "visitor". When encountering a MemberExpression or MethodCallExpression, you would check the member's declaring type - if it is the one ou don't want, recreate it (Expression.PropertyOrField is useful here).

Note that you can't do this just at the places it is used; the entire tree must be regenerated. I'm not at a PC at the moment, but if you want I can do an example later; leave a comment if you need this example.

Note that this is somewhat complicated by the int/long and char/string mismatch.

1 Comment

Yes, please. Give me an example.
0
public CategoryViewModel GetSingle( Expression<Func<CategoryViewModel, bool>> where)
        {
            Expression<Func<DAL.EntityModels.Category, CategoryViewModel>> converter =
                c => ToBll(c);

            var param = Expression.Parameter(typeof(DAL.EntityModels.Category), "category");
            var body = Expression.Invoke(where, Expression.Invoke(converter, param));
            var lambda = Expression.Lambda<Func<DAL.EntityModels.Category, bool>>(body, param);

            return  (CategoryViewModel )_categoryRepository.GetSingle(lambda);

        }

//..............
public T GetSingle(Expression<Func<T, bool>> where)
        {
            return this.ObjectSet.Where(where).FirstOrDefault<T>();
        }

Comments

0

You could compile the first expression to a delegate and then convert it with
NJection.LambdaConverter which is a library that converts delegates to expression trees.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.