如何从字符串表达式中获取值

时间:2013-09-26 22:19:35

标签: c# linq reflection dynamic-linq linq-expressions

我的数据库中存储了一个字符串:

"Users.ElementAt(1).LastName"

然后我有一个像这样的对象:

        MyClass myclass = new MyClass ()
        {
            Users = new List<User>()
            {
                new User()
                {
                    LastName = "LastName1"
                },
                new User()
                {
                    LastName = "LastName2"
                },
            }
        };  

有没有办法解析/评估/运行针对我的对象的给定字符串以获得每个用户的姓氏?

我一直在使用DynamicLinq库,但我遇到了ElementAt(1)的问题,并显示错误消息:

“没有适用的聚合方法'ElementAt'存在”

有人可以在这里提供一些指导吗?我是否不得不求助于编写自己的解析器并使用反射?

3 个答案:

答案 0 :(得分:0)

我不确定你是否真的需要动态linq来做你想做的事。只是常规的System.Linq应该处理找到位置的索引,并且如果你在我的经验中使用C#.NET 4.5或4.0,那么元素应该可以正常工作。这是一个简单的控制台应用程序应该可以正常工作:

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


public class User
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}


class Program
{
    public static List<User> Users;

    static void Main(string[] args)
    {
            Users = new List<User>
            {
                new User
                    {
                        FirstName = "Brett",
                        LastName = "M"
                    },
                new User
                    {
                        FirstName = "John",
                        LastName = "Doe"
                    },
            new User
                {
                    FirstName = "Sam",
                    LastName = "Dilat"
                }
            };

        Console.WriteLine("Should work as long as object is defined and instantiated");
        Console.WriteLine(Users.ElementAt(1).FirstName);


        Console.WriteLine("\nIterate Through List with Linq\n I use a string you can add to another list or whatever\n\n");

        string s = "";

        Users.ForEach(n => s += "Position: " + Users.IndexOf(n) + " " + n.LastName + Environment.NewLine);
        Console.WriteLine(s);

        Console.ReadLine();
    }

}

如果您只想通过该集合的属性在集合中查找特定对象,则可以使用“FindIndex”方法:

Console.WriteLine("Index of Dilat: " + Users.FindIndex(n => n.LastName.Equals("Dilat")));

编辑9-27-13以便分割字符串。

如果你想获取一个字符串并将其拆分成一个很好的可用列表来迭代,你也可以这样做。你只需要找到分离器。如果你没有,你将不得不使用一些更复杂的正则表达式魔法。

保持一切相同但用我的MAIN方法代替:

string split = "Brett,Same,John,Frank";

        List<string> stringList = split.Split(',').ToList();

        string s = "";

        stringList.ForEach(n => s += n + Environment.NewLine);

        s += "\n\nFor Observing Element at\n";

        s += "John is at: " + stringList.FindIndex(n => n.Equals("John"));

        s += "\n\nGetting Poco Objects assigned and listed\n";

        var list = stringList.Select(u => new User
            {
                FirstName = u,
                LastName = "Something"
            }).ToList();

        list.ForEach(n => s += "User: " + n.FirstName + " " + n.LastName + "At: " + list.IndexOf(n) + Environment.NewLine);

答案 1 :(得分:0)

var allLastNamesInList= Users.Select(x=> x.LastName).toList();

此语句将遍历列表并获取所有姓氏。您甚至可以使用订单,以便按顺序获得姓氏。

这是您要求的要求还是其他不同的东西?

答案 2 :(得分:0)

看起来DynamicLinq的表达式解析器仅支持标准LINQ运算符方法的子集:

interface IEnumerableSignatures
{
    void Where(bool predicate);
    void Any();
    void Any(bool predicate);
    void All(bool predicate);
    void Count();
    void Count(bool predicate);
    void Min(object selector);
    void Max(object selector);
    void Sum(int selector);
    void Sum(int? selector);
    void Sum(long selector);
    void Sum(long? selector);
    void Sum(float selector);
    void Sum(float? selector);
    void Sum(double selector);
    void Sum(double? selector);
    void Sum(decimal selector);
    void Sum(decimal? selector);
    void Average(int selector);
    void Average(int? selector);
    void Average(long selector);
    void Average(long? selector);
    void Average(float selector);
    void Average(float? selector);
    void Average(double selector);
    void Average(double? selector);
    void Average(decimal selector);
    void Average(decimal? selector);
    void Take(int count);
    void Union(IQueryable right);
    void OrderBy(LambdaExpression exp);
    void OrderByDescending(LambdaExpression exp);
}

如您所见,ElementAt不在其中。好消息是,只需将void ElementAt(int index);添加到IEnumerableSignatures似乎就可以了。当然,假设您使用的LINQ查询提供程序将处理ElementAt运算符;它完全有可能不会。

但是如果修改DynamicLinq源不是一个选项,那么不,核心.NET Framework或LINQ中没有可以解析和评估这些表达式的工具。还有其他选择(参见ScriptCS,Roslyn),但我怀疑你正在向你想要解决的任何实际问题的“过度杀伤”解决方案漂移。