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)}