0

My case is conversion expressions from model A to model B.

Example

Expression<Func<Model, Contract>> conversionExpression = model => new Contract
{
    Name = model.Name,
    Description = model.Description,
    Type = model.Type == "A" ? 1 : model.Type == "B" ? 2 : 3
};

class Model
{
    public string Name { get; set; }
    public string Description { get; set; }
    public string Type { get; set; }
}


class Contract
{
    public string Name { get; set; }
    public string Description { get; set; }
    public int Type { get; set; }
}

Some conversion expressions have common blocks of code that I want to separate into reusable expression.

For example

Expression<Func<Model, Contract>> conversionExpression1 = model => new Contract
{
    Name = model.Name,
    Description = model.Description,
    Type = model.Type == "A" ? 1 : model.Type == "B" ? 2 : 3
};


Expression<Func<Model, Contract>> conversionExpression2 = model => new Contract
{
    Name = model.Name + "123",
    Description = model.Name + " " + model.Description,
    Type = model.Type == "A" ? 1 : model.Type == "B" ? 2 : 3
};

conversionExpression1 and conversionExpression2 have a common way of calculating the Type field. So I created expression for Type conversion.

Expression<Func<string, int>> commonTypeConversionExpression = 
    typeStr => typeStr == "A" ? 1 : typeStr == "B" ? 2 : 3;

How can I reuse commonTypeConversionExpression in conversionExpression1 and conversionExpression2 without compiling it?

Expression<Func<Model, Contract>> conversionExpression1 = model => new Contract
{
    Name = model.Name,
    Description = model.Description,
    Type = commonTypeConversionExpression.Compile().Invoke(model.Type)
};

Compiling is not a solution because Expressions may be used for query generation. And it is important to preserve the original expression tree.

Which looks like this:

model => new Contract() {Name = model.Name, Description = model.Description, Type = IIF((model.Type == "A"), 1, IIF((model.Type == "B"), 2, 3))}}

But not like this:

model => new Contract() {Name = model.Name, Description = model.Description, Type = value(Program+<>c__DisplayClass0_0).commonTypeConversionExpression.Compile().Invoke(model.Type)}
Tima
  • 119
  • 1
  • 2
  • 1
    The short answer is that there's no built-in facility to do what you want easily. You'll either have to learn how to compose expreession trees yourself via the `Expression.*` methods, or find a library that does what you want. – Kirk Woll May 31 '22 at 21:32

0 Answers0