2016-10-11 6 views
-1

別のIQueryableをパラメータとして扱うためにLINQ式セレクタを作成しようとしています。 dot.netのフィドルは、私がIQueryable parameterを受け入れ、場合によっては、セレクタに適用するCustomSelectorをコーディングしようとしていますhere式<Func <TSource、TResult >>セレクタwithパラメータ

です。

CustomSelector IQueryableパラメータに適用する各行の値も含める必要があります。

このようにして、2つのカスタムセレクタを書く必要はありません。

代替はGetMyData2の機能です。

テストコードは以下の通りです:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 

public class Entity 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

public class EntityDto 
{ 
    public int Id { get; set; } 
    public string Name { get; set; }  
    public int Count { get; set; } 
} 

public class TestController 
{ 
    public List<Entity> entityList { get; set; } 


    public List<EntityDto> GetMyData(string condition) 
    { 
     List<Entity> sourceEntityList = new List<Entity>(); 
     List<EntityDto> returnEntityList = new List<EntityDto>(); 

     switch(condition) 
     { 
      case "A":  
      returnEntityList = sourceEntityList.Where(x=>x.Name == "A").Select(y=>CustomSelector(sourceEntityList.Where(z=>z.Name=x.Name))); 
     return returnEntityList; 
      break; 
     case "B":  
     default: 
      returnEntityList = sourceEntityList.Where(x=>x.Name == "B").Select(y=>CustomSelector(sourceEntityList.Where(z=>z.Name != x.Name))); 
     return returnEntityList; 
      break; 
     } 

    } 

    public List<EntityDto> GetMyData2(string condition) 
    { 
     List<Entity> sourceEntityList = new List<Entity>(); 
     List<EntityDto> returnEntityList = new List<EntityDto>(); 

     switch(condition) 
     { 
      case "A":  
      returnEntityList = sourceEntityList.Where(x=>x.Name == "A").Select(ent=> 
                       new EntityDto() 
       { 
        Id = ent.Id 
        , 
        Name = ent.Name          
        , 
        Count = sourceEntityList.Count(z=>z.Name== ent.Name) 
       } 
                      ).ToList(); 
     return returnEntityList; 
      break; 
     case "B":  
     default: 
      returnEntityList = sourceEntityList.Where(x=>x.Name == "B").Select(ent=> 
                       new EntityDto() 
       { 
        Id = ent.Id 
        , 
        Name = ent.Name          
        , 
        Count = sourceEntityList.Count(z=>z.Name != ent.Name) 
       } 
                      ).ToList(); 
     return returnEntityList; 
      break; 
     } 

    } 

    protected Func<Entity, EntityDto> CustomSelector(IQueryable<Entity> paramQuery) 
     { 

       return ent => new EntityDto() 
       { 
        Id = ent.Id 
        , 
        Name = ent.Name          
        , 
        Count = paramQuery.Count() 
       }; 

     } 
} 
+0

そして、あなたの質問は... –

+0

別のIQueryableをパラメータとして扱うためにLINQ式セレクタを作成するにはどうすればよいですか? –

答えて

1

あなたは何を求めているいくつかの式ツリー操作O/Wできません。

あなたはLinqKitAsExpandable/Invoke)またはAutoMapperのようないくつかのサードパーティ製のパッケージを使用しますが、ここでは表現プロトタイプとシンプルなパラメータの代用に基づいたカスタムソリューションであることができます。

パラメータ代用品:

public static class ExpressionUtils 
{ 
    public static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target) 
    { 
     return new ParameterReplacer { Source = source, Target = target }.Visit(expression); 
    } 

    class ParameterReplacer : ExpressionVisitor 
    { 
     public ParameterExpression Source; 
     public Expression Target; 
     protected override Expression VisitParameter(ParameterExpression node) 
     { 
      return node == Source ? Target : base.VisitParameter(node); 
     } 
    } 
} 

CustomSelector:

protected Expression<Func<Entity, EntityDto>> CustomSelector(Expression<Func<Entity, IQueryable<Entity>>> paramQuery) 
{ 
    Expression<Func<Entity, IQueryable<Entity>, EntityDto>> prototype = (e, q) => new EntityDto 
    { 
     Id = e.Id, 
     Name = e.Name, 
     Count = q.Count(), 
    }; 
    return Expression.Lambda<Func<Entity, EntityDto>>(
     prototype.Body 
      .ReplaceParameter(prototype.Parameters[0], paramQuery.Parameters[0]) 
      .ReplaceParameter(prototype.Parameters[1], paramQuery.Body), 
     paramQuery.Parameters[0]); 
} 

用途:?

public List<EntityDto> GetMyData(string condition) 
{ 
    var sourceEntityList = new List<Entity>().AsQueryable(); 
    switch (condition) 
    { 
     case "A": 
      return sourceEntityList.Where(x => x.Name == "A") 
       .Select(CustomSelector(x => sourceEntityList.Where(y => y.Name == x.Name))).ToList(); 
     case "B": 
     default: 
      return sourceEntityList.Where(x => x.Name == "B") 
       .Select(CustomSelector(x => sourceEntityList.Where(y => y.Name != x.Name))).ToList(); 
    } 
} 
+0

ありがとうございました。 なぜdownvotesしかし、彼らはコメントを残していないか分からない。 私は持っているそれぞれのケースごとに異なるセレクターを書いておく方が良いでしょうか? –

+0

私はそれぞれの場合についての最後の質問を理解しているとは思えません。このサンプルでは1つの 'CustomSelector'メソッドしか表示されていません。 –

+0

おそらく 'prototype.Body.BetaReduce(paramQuery.Parameters [0]、paramQuery.Body)'のように、すべてのパラメータを一度に置き換えるともっと美しいでしょうか? –

関連する問題