0

I'm trying to figure out if it is at all possible to combine 2 LambdaExpressions, where one lambda expression uses a Child property of the first.

Given the following 2 classes:

class MyClass
{
    public string Name { get; set; }
    public SubClass Child { get; set; }
}

class SubClass
{
    public string SubClassName { get; set; }
}

And the following expressions:

Expression<Func<MyClass, bool>> Expression1 = c => c.Name == "Test";

Expression<Func<SubClass, bool>> Expression2 = sc => sc.SubClassName == "SubTest";

I'd like to combine it to a lambda of the following type:

Expression<Func<MyClass, bool>> Combined;

Reason being: The upper lambda is internal, and the lower lamba would be passed in by the 'user' of the method, which has no idea (nor should he) that MyClass exists, has only knowledge of SubClass.

Is this at all possible, or should I find another road to follow?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
RVandersteen
  • 2,067
  • 2
  • 25
  • 46

1 Answers1

-1

I don't know if it's exactly what you're after, but;

public class Search
{
    private IEnumerable<MyClass> _data;

    public Search(IEnumerable<MyClass> data)
    {
        _data = data;
    }

    public IEnumerable<MyClass> Find(Expression<Func<SubClass, bool>> expr)
    {
        ParameterExpression x = Expression.Parameter(typeof(MyClass), "x");
        PropertyInfo p = typeof(MyClass).GetProperty("Child");

        var propertyExpression = (expr.Body as BinaryExpression).Left as MemberExpression;
        var constant = (expr.Body as BinaryExpression).Right;

        var memberAccess = Expression.MakeMemberAccess(x, p);
        var upperMemberAccess = Expression.MakeMemberAccess(memberAccess, propertyExpression.Member);

        var equals = Expression.Equal(upperMemberAccess, constant);

        var expression = Expression.Lambda<Func<MyClass, bool>>(equals, x);

        return _data.Where(expression.Compile());
    }
}

And then using it looks like this;

var search = new Search(new[] {
        new MyClass { Name = "Test 1", Child = new SubClass { SubClassName = "Bob" }},
        new MyClass { Name = "Test 2", Child = new SubClass { SubClassName = "Subclass"}},
        new MyClass { Name = "Test 3", Child = new SubClass { SubClassName = "Subclass"}}
    });

    search.Find(k => k.SubClassName == "Subclass");

I'm certain there is a better way of doing this, as this feels clunky, but basically it will find all members of MyClass that have a subclass with the name 'Subclass'. It extracts the components of the binary expression handed (x => x.SubClassname == "Subclass" ), and rebuilds a new expression with equals based of MyClass.

tbddeveloper
  • 2,407
  • 1
  • 23
  • 39