LINQ:Expression.Call(typeof(可查询),"选择"

Mik*_*ike 3 lambda projection linq-to-sql

我正在尝试创建一个小的"automapper-esq"实用程序,它将采用LinqToSql实体并将其映射到"投影类".

到目前为止,我有这样的事情:

class Entity
{
    public int ID { get; set; }
    public string WantedProperty { get; set; }
    public string UnWantedPropertyData { get; set; }
    ...More Unwanted Properties...
    public IEnumerable<ChildEntity> ChildEntities { get; set; }
}

class EntityProjection
{
    public int ID { get; set; }
    public string WantedProperty { get; set; }
    public IEnumerable<ChildEntityProjection> ChildEntities { get; set; }
}

class ChildEntityProjection
{
    public int ID { get; set; }
    public string WantedProperty { get; set; }
    public string UnWantedPropertyData { get; set; }
    ...More Unwanted Properties...
}


var results = context.Table.Select(ProjectionHelper.BuildProjection<Entity,EntityProjection>());
Run Code Online (Sandbox Code Playgroud)

BuildProjection返回的位置:

Expression<Func<TSource, TResult>>
Run Code Online (Sandbox Code Playgroud)

这基本上创建了一个像这样的lambda:

A => new EntityProjection() { ID = A.ID, WantedProperty = A.WantedProperty }
Run Code Online (Sandbox Code Playgroud)

现在棘手的部分......我希望能够投射"父"实体的关联属性.基本上我需要的是得到这样的东西:

A => new EntityProjection() {
  ID = A.ID,
  WantedProperty = A.WantedProperty,
  ChildEntities = A.ChildEntities.Select(B => new ChildEntityProjection {
    ID = B.ID,
    WantedProperty = B.WantedProperty
  }
}
Run Code Online (Sandbox Code Playgroud)

我得到了这个部分:

A => new EntityProjection() {
  ID = A.ID,
  WantedProperty = A.WantedProperty,
  ChildEntities = System.Collections.Generic.List1[ChildEntity].Select(B => new ChildEntityProjection {
    ID = B.ID,
    WantedProperty = B.WantedProperty
  }
}
Run Code Online (Sandbox Code Playgroud)

通过做这个:

IQueryable<ChildEntity> list = new List<ChildEtity>().AsQueryable();
Expression _selectExpression = Expression.Call(
  typeof(Queryable),
  "Select",
  new Type[] { typeof(ChildEntity), typeof(ChildEntityProjection) },
  Expression.Constant(list),
  _nestedLambda);
Run Code Online (Sandbox Code Playgroud)

这是我现在陷入困境的地方......当我尝试用表示属性的实际数据类型的其他表达式替换Expression.Constant(list)时,我感到有些困惑,因此"System.Collections.Generic.List1 [ChildEntity].选择(B => ..."将替换为"A.ChildEntities.Select(B => ..."

有任何想法吗?

Mik*_*ike 7

我正在寻找更多如何使用表达式(正确的术语?)这样做,我最终弄明白了.

我不得不改变这个:

IQueryable<ChildEntity> list = new List<ChildEtity>().AsQueryable(); 
Expression _selectExpression = Expression.Call( 
  typeof(Queryable), 
  "Select", 
  new Type[] { typeof(ChildEntity), typeof(ChildEntityProjection) }, 
  Expression.Constant(list), 
  _nestedLambda); 
Run Code Online (Sandbox Code Playgroud)

对此:

MethodInfo selectMethod = null;
foreach (MethodInfo m in typeof(Enumerable).GetMethods().Where(m => m.Name == "Select"))
  foreach (ParameterInfo p in m.GetParameters().Where(p => p.Name.Equals("selector")))
    if (p.ParameterType.GetGenericArguments().Count() == 2)
      selectMethod = (MethodInfo)p.Member;

var _selectExpression = Expression.Call(
  null,
  selectMethod.MakeGenericMethod(new Type[] { typeof(ChildEntity), typeof(ChildEntityProjection) }),
  new Expression[] { _myPropertyExpression, _myFuncExpression });
Run Code Online (Sandbox Code Playgroud)

希望这有助于其他人...