0

I have following situation:

public class BaseClass
{
public string Field1 { get; set; }
public string Field2 { get; set; }
public string Field3 { get; set; }    
}

public class Product: BaseClass
{
/* Some methods*/
}

public class Country: BaseClass
{
/* Some methods*/
}

public class MyCustomClass
{
public Product Product { get; set; }
public Country Country { get; set; }    
}

I want to create a list of expressions which I would later use to query my MyCustomClass, example

var listOfExpressions= new List<Expression<Func<MyCustomClass, bool>>>();

if (x == 1)
    listOfExpressions.Add(x => x.Product.Field1 == "Fruit")
/*.
  .
  .*/
if (y == 2)
    listOfExpressions.Add(x => x.Country.Field2 == "Western")
} 

Now this looks really ugly with these bunch of Ifs and I would prefer to have a method in BaseClass for which you would pass int ({1,2,3}) and it would return me the expression. The problem is that I need to have expression of type <MyCustomClass, bool> but in my BaseClass I can't directly get that, is there an way I could acheive this without complicating code too much?

I am thinking about something like this:

public class BaseClass
{
public string Field1 { get; set; }
public string Field2 { get; set; }
public string Field3 { get; set; }    

protected Expression<Func<BaseClass, bool>> GetExpression(int key, string value)
{
        switch (key)
        {
            case 1:
                return x => x.Field1 == value;
            case 2:
                return x => x.Field2 == value;
            case 3:
                return x => x.Field3 == value;
        }
}

By now I am stuck of how to get Expression<Func<BaseClass, bool>> to be used in Expression<Func<MyCustomClass, bool>>.

EDIT: The purpose of the expression:

I want to constuct a list of expressions to later use it to query database using Entity framework core. Example:

    var query = DbContext.MyCustomClass.AsQueryable();

    foreach (var expression in listOfExpressions)
    {
        query = query.Where(expression);
    }
Ramūnas
  • 1,494
  • 18
  • 37
  • Could you elaborate what the actual problem you try to solve is? Why you need the Expression for example – X39 Sep 20 '18 at 10:59
  • I don't see what you get from moving into the base class. You still have branching logic (switch vs. if). Why not put it into `MyCustomClass` instead? – juharr Sep 20 '18 at 11:03
  • @X39 I have updated the question with the example why I want expressions. By moving it to base class I would need it to write just once (all derived classes use same logic), hence less maintenance – Ramūnas Sep 20 '18 at 11:15
  • [Favour composition over inheritance](https://stackoverflow.com/questions/49002/prefer-composition-over-inheritance). I'd just add a helper method and call that. Inheritance almost always becomes a rod for your own back. – Liam Sep 20 '18 at 11:24
  • It still did not explained what the actual problem is.. What are you trying to archive exactly, word the whole problem, not only parts of it. Why you want to query a list of expressions against EF for example is not clear. With the proper question asked, a proper answer may follow. Right now, it still is not clear to me what you want to archive exactly with that approach and why those weird number sare in use. *Start at the beginning and not inbetween* – X39 Sep 20 '18 at 12:06

1 Answers1

0

You can build your Expression on you own. Just add another parameter to GetExpression:

public static Expression<Func<MyCustomClass, bool>> GetExpression(
    string derrivedName, // "Product" or "Country"
    int fieldId,
    string value)
{
    var x = Expression.Parameter(typeof(MyCustomClass), "x");
    var lambda = Expression.Lambda<Func<MyCustomClass, bool>>(
        Expression.Equal(
            Expression.Constant(value),
            Expression.PropertyOrField(
                Expression.PropertyOrField(x, derrivedName),
                $"Field{fieldId}")
            ), 
            x);

    return lambda;
}

Now you can use it like:

var exp3 = GetExpression("Product", 1, "Fruit");

This line will create an expression x => ("Fruit" == x.Product.Field1)

Aleks Andreev
  • 7,016
  • 8
  • 29
  • 37