My application contains several business layer types. I create them from Entity Framework entities using linq expressions. Below I put sample code that should describe my current solution. Please consider, that this is only simple example. My real business layer types are much more complex.
public class SimpleType
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public static Expression<Func<simple_type_entity, SimpleType>> CreateExpression()
{
return arg => new SimpleType
{
Id = arg.id,
Name = arg.name,
Description = arg.desc
}
}
}
public class ComplexType
{
public Guid Id { get; set; }
public SimpleType Property1 { get; set; }
public SimpleType Property2 { get; set; }
public static Expression<Func<complex_type_entity, ComplexType>> CreateExpression()
{
return arg => new ComplexType
{
Id = arg.id,
Property1 = new SimpleType
{
Id = arg.property1.id,
Name = arg.property1.name,
Description = arg.property1.desc
},
Property2 = new SimpleType { .... }
}
}
}
You can notice that ComplexType
creates SimpleType
many times and SimpleType
creation code is duplicated. How can I call linq expression from another expression? I would like to use SimpleType.CreateExpression()
in all places where SimpleType
is created. I use linq expressions, because as I know, expressions are translated to sql queries, so new solution should be also translated to sql queries / compatible with linq to entieties.
This first version does not work when used on an IQueryable. (only on an IEnumerable) Scroll to the final version in this post to get the IQueryable-working version.
public class ComplexType
{
public Guid Id { get; set; }
public SimpleType Property1 { get; set; }
public SimpleType Property2 { get; set; }
public static Expression<Func<complex_type_entity, ComplexType>> CreateExpression()
{
var compiledSimpleTypeFnc = SimpleType.CreateExpression().Compile();
return arg => new ComplexType
{
Id = arg.id,
Property1 = compiledSimpleTypeFnc(arg.property1),
Property2 = compiledSimpleTypeFnc(arg.property2)
};
}
}
or if you really want to keep it as an expression to the very end:
public class ComplexType
{
public Guid Id { get; set; }
public SimpleType Property1 { get; set; }
public SimpleType Property2 { get; set; }
public static Expression<Func<complex_type_entity, ComplexType>> CreateExpression()
{
var expr = SimpleType.CreateExpression();
return arg => new ComplexType
{
Id = arg.id,
Property1 = expr.Compile()(arg.property1),
Property2 = expr.Compile()(arg.property2)
};
}
}
Edit: The below code works with entity framework.
using System;
using System.Linq.Expressions;
using ConsoleApplication2;
using System.Linq;
class Program2
{
public static void Main(string[] args)
{
using (var db = new TestEntities())
{
var exp = db.complex_type_entity.Select(ComplexType.CreateExpression()).First();
}
}
}
public class SimpleType
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public static Expression<Func<simple_type_entity, SimpleType>> CreateExpression()
{
var parameterExpr = Expression.Parameter(typeof(simple_type_entity), "p0");
return Expression.Lambda<Func<simple_type_entity, SimpleType>>(CreateExpression(parameterExpr), parameterExpr);
}
public static MemberInitExpression CreateExpression(Expression sourceExpr)
{
return Expression.MemberInit(
Expression.New(typeof(SimpleType)),
Expression.Bind(typeof(SimpleType).GetProperty("Id"), Expression.Property(sourceExpr, "id")),
Expression.Bind(typeof(SimpleType).GetProperty("Name"), Expression.Property(sourceExpr, "name")),
Expression.Bind(typeof(SimpleType).GetProperty("Description"), Expression.Property(sourceExpr, "desc")));
}
}
public class ComplexType
{
public Guid Id { get; set; }
public SimpleType Property1 { get; set; }
public SimpleType Property2 { get; set; }
public static Expression<Func<complex_type_entity, ComplexType>> CreateExpression()
{
var parameterExp = Expression.Parameter(typeof(complex_type_entity), "p0");
return Expression.Lambda<Func<complex_type_entity, ComplexType>>(
Expression.MemberInit(
Expression.New(typeof(ComplexType)),
Expression.Bind(typeof(ComplexType).GetProperty("Id"), Expression.Property(parameterExp, "id")),
Expression.Bind(typeof(ComplexType).GetProperty("Property1"), SimpleType.CreateExpression(Expression.Property(parameterExp, "simple_type_entity"))),
Expression.Bind(typeof(ComplexType).GetProperty("Property2"), SimpleType.CreateExpression(Expression.Property(parameterExp, "simple_type_entity1")))),
parameterExp);
}
}