![](/img/trans.png)
[英]C# Syntax - Example of a Lambda Expression - ForEach() over Generic List
[英]c# List<string> to Lambda Expression with starter example: Refactor to handle the List
我有这个:
List<string> fields;
fields[0] = "firstFieldName";
fields[1] = "secondFieldName";
...
fields[n] = "nthFieldName";
我想得到这个:
var selector = p => new {p.firstField, p.secondField, ..., p.nthFieldName}
// selector is of type Expression<Func<Entity, object>>
GoofBallLogic的 代码很相似,最后以p => p.column
// Entity is an object in a diagram from Entity Framework 4
var p = Expression.Parameter(typeof(Entity, "p");
var selector = Expression.Lambda<Func<Entity, string>(
Expression.Property(p, columnToGroupBy), p );
编辑:我想完成的事情
我有一个“通用”存储库:
public class Repository<E, C> : IRepository<E,C>
{
private C _dc {get;set;} // ObjectContext (Entity Framework 4)
private string _entityName {get;set;}
public string entityKeyName {get;private set;}
public List<string> entityKeys {get;private set;}
public Expression<Func<E, object>> entityKey {get;private set;}
private EntityContainer _containerName {get;set;}
public Repository(C myDC)
{ _dc = myDC; // TODO: check for null
// Name of "this" ObjectContext
_containerName = _dc.MetadataWorkspace.GetEntityContainer(
_dc.DefaultContainerName, DataSpace.CSpace);
// Name of "this" Entity
_entityName = _containerName.BaseEntitySets
.Where(p => p.ElementType.Name == typeof (E).Name)
.Select( p => p.Name).FirstOrDefault();
// String list of the keys
entityKeys = _containerName
.BaseEntitySets.First(meta => meta.ElementType.Name ==
typeof(E).Name)
.ElementType.KeyMembers.Select(k => k.Name).ToList();
// Thanks Jon Skeet for this cool comma sep list formula
entityKeyName = string.Join(",", entityKeys.ToArray() );
entityKey = Expression.Lambda<Func<E, object>> ...
将LinerKey设置为可在OrderBy语句中使用的对象的方法,因为Linq to Entities需要在执行.Skip()。Take()之前对集合进行排序。
编辑:
令人惊讶的是,Orderby可以采取以下措施:
p => "field1,field2,field3"
这允许我的代码执行,但实际上不按字段值对项目进行排序。 我猜这是TDD的第一步:使用文字。
我发现了一个有趣的问题,花了一些时间来解决,并找到了一种相对简单的方法。
无论如何,这是一个有关如何进行单个字段排序的示例(我将使用第一个字段),如果您想对更多字段进行排序,则还必须为其创建表达式并在之后使用.ThenBy(xxx)通常的OrderBy(xxx)。
// Create a parameter which passes the object
ParameterExpression param = Expression.Parameter(typeof(E), "a");
// Create body of lambda expression
Expression body = Expression.PropertyOrField(param, fieldname);
// Create lambda function
Expression<Func<E, string>> exp = Expression.Lambda<Func<E, string>>(body, param);
// Compile it so we can use it
Func<E, string> orderFunc = exp.Compile();
现在,您可以执行OrderBy(orderFunc),它将按fieldname中命名的属性对列表进行排序。 唯一的缺点是它仅适用于字符串字段(表达式的返回值)。 也许也可以解决这个问题。
修复可与任何IComparable类型一起使用:
// Create a parameter which passes the field
ParameterExpression param = Expression.Parameter(typeof(E), "a");
// Create body of lambda expression
Expression body = Expression.TypeAs(Expression.PropertyOrField(param, fieldname), typeof(IComparable));
// Create lambda function
Expression<Func<E, IComparable>> exp = Expression.Lambda<Func<E, IComparable>>(body, param);
// Compile it so we can use it
Func<E, IComparable> orderFunc = exp.Compile();
您不能轻易做到这一点,因为您无法为运行时不存在的类型构造new
表达式。 (您可以在C#中使用匿名类型,因为C#编译器会为您创建类型。)
如果您想真正地做到这一点,则可以生成一个动态程序集并实际创建所需的类型。 这里有一个简短的例子 。
我怀疑有更简单的方法。 我们需要知道您的目标(该表达式树需要做什么),而您尚未说明。
从您编辑的问题来看,您似乎只想能够通过多个键进行订购。 只需使用.OrderBy()
和.ThenBy()
就可以轻松实现。 我假设您在这里使用IQueryable<E>
:
IQueryable<E> query = ...;
IOrderedQueryable<E> ordered = null;
foreach (var key in entityKeys)
{
// Code from Doggett to construct the lambda expression for one step
ParameterExpression param = Expression.Parameter(typeof(E), "a");
var body = Expression.TypeAs(
Expression.PropertyOrField(param, key),
typeof(IComparable));
var exp = Expression.Lambda<Func<E, IComparable>>(body, param);
if (ordered == null)
ordered = query.OrderBy(exp);
else
ordered = ordered.ThenBy(exp);
}
var finalQuery = (ordered ?? query).Skip(n).Take(m);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.