我正在尝试创建一个LINQ表达式选择器来容纳另一个IQueryable作为参数。 dot.net小提琴是here
我正在尝试对 CustomSelector 进行编码以接受IQueryable parameter
并根据具体情况将其应用于选择器。
另外,我想在 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 :(得分:1)
你在问什么是不可能没有一些表达式树操作。
您可以使用某些第三方软件包,例如LinqKit(AsExpandable
/ 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();
}
}