Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>You have to analyze the parameters and the body of the LambdaExpression and build a new one. You can access the body it using <code>predicate.Body</code> and the parameters using predicate.Parameters. The new expression has a parameter of type UserBO instead of UserDataObject. In addition, the ParameterExpression(s) in the body must use the new parameter.<br/> Of course, this assumes that it is a simple scenario where the BO and the DataObject have the same properties. More complex transformations are possible but need a deeper analysis of the expression tree.<br/> In order to vive you a starting Point, I out together a sample with a very similar BusinessObject and DataObject. The key component is a class derived from ExpressionVisitor that performs the conversion:</p> <pre><code>using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; namespace ConvertExpression { public class BusinessObject { public int Value { get; set; } } public class DataObject { public int Value { get; set; } } internal class ExpressionConverter : ExpressionVisitor { public Expression Convert(Expression expr) { return Visit(expr); } private ParameterExpression replaceParam; protected override Expression VisitLambda&lt;T&gt;(Expression&lt;T&gt; node) { if (typeof(T) == typeof(Func&lt;BusinessObject, bool&gt;)) { replaceParam = Expression.Parameter(typeof(DataObject), "p"); return Expression.Lambda&lt;Func&lt;DataObject, bool&gt;&gt;(Visit(node.Body), replaceParam); } return base.VisitLambda&lt;T&gt;(node); } protected override Expression VisitParameter(ParameterExpression node) { if (node.Type == typeof(BusinessObject)) return replaceParam; // Expression.Parameter(typeof(DataObject), "p"); return base.VisitParameter(node); } protected override Expression VisitMember(MemberExpression node) { if (node.Member.DeclaringType == typeof(BusinessObject)) { var member = typeof(DataObject).GetMember(node.Member.Name, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).FirstOrDefault(); if (member == null) throw new InvalidOperationException("Cannot identify corresponding member of DataObject"); return Expression.MakeMemberAccess(Visit(node.Expression), member); } return base.VisitMember(node); } } public class ConvertExpression { public static void Main() { BusinessObject[] bos = { new BusinessObject() { Value = 123 }, new BusinessObject() { Value = 246 } }; DataObject[] dos = { new DataObject() { Value = 123 }, new DataObject() { Value = 246 } }; Expression&lt;Func&lt;BusinessObject, bool&gt;&gt; boExpr = x =&gt; x.Value == 123; var conv = new ExpressionConverter(); Expression&lt;Func&lt;DataObject, bool&gt;&gt; doExpr = (Expression&lt;Func&lt;DataObject, bool&gt;&gt;) conv.Convert(boExpr); var selBos = bos.Where(boExpr.Compile()); Console.WriteLine("Matching BusinessObjects: {0}", selBos.Count()); foreach (var bo in selBos) Console.WriteLine(bo.Value); var compDoExpr = doExpr.Compile(); var selDos = dos.Where(doExpr.Compile()); Console.WriteLine("Matching DataObjects: {0}", selDos.Count()); foreach (var dataObj in selDos) Console.WriteLine(dataObj.Value); Console.ReadLine(); } } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload