2010-10-13 2 views
2

Я пытаюсь создать небольшой «automapper-ESQ» утилита, которая будет принимать LinqToSql объект и отобразить его на «проекции класса»LINQ: Expression.Call (TypeOf (Queryable), «Выбрать»

.

до сих пор у меня есть что-то вроде этого:

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>()); 

где BuildProjection возвращается:

Expression<Func<TSource, TResult>> 

, который по существу создает лямбда так:

A => new EntityProjection() { ID = A.ID, WantedProperty = A.WantedProperty } 

Теперь сложная часть ... Я хотел бы также проектировать свойства ассоциации «родительского» объекта. По сути то, что мне нужно, чтобы получить что-то вроде этого:

A => new EntityProjection() { 
    ID = A.ID, 
    WantedProperty = A.WantedProperty, 
    ChildEntities = A.ChildEntities.Select(B => new ChildEntityProjection { 
    ID = B.ID, 
    WantedProperty = B.WantedProperty 
    } 
} 

Я получил по мере получения этой части:

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

Делая это:

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

Вот где я я застрял в данный момент ... Я немного запутался при попытке заменить Expression.Constant (list) другим выражением, которое представляет фактический тип данных для свойства, чтобы «System.Collections.Generic.List 1 [ChildEntity] .Выберите (B => ... "замените на" A.ChildEntities.Select (B => ... "

Любые идеи?

ответ

5

Я искал больше для того, как это сделать с помощью выражений (правильная терминология?), И я в конце концов понял это.

мне пришлось изменить:

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

к этому:

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

Надеется, что это помогает кто-то еще ...

0

Предлагаемый запрос. И вы можете изменить свой IEnumerable <> в EntityProjection на список <>, чтобы избежать ленивой загрузки (если это имеет значение ...). Во всяком случае, я надеюсь, что это будет полезно.

EntityProjection projection = context.Table 
    .Where(entity => entity.ID == 123) 
    .Select(entity => new EntityProjection() 
    { 
     ID = entity.ID, 
     WantedProperty = entity.WantedProperty, 
     ChildEntities = entity.ChildEntities 
      .Select(child => new ChildEntityProjection() 
      { 
       ID = child.EmployeeID, 
       WantedProperty = child.WantedProperty 
      }) 
      .ToList() 
    }) 
    .SingleOrDefault(); 
Смежные вопросы