繁体   English   中英

C#列表 <string> 入门示例访问Lambda Expression:重构以处理列表

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM