2

我有一个枚举如下:

 IEnumerable<dynamic> collection = new 
 {  
    column1 = "1", column2 = "name", column3= "somevalue" 
 }, 
 new 
 { 
    column1 = "2",   column2 = "name2", column3= "somevalue2" 
 },
 new 
 { 
    column1 = "3", column2 = "name3", column3= "somevalue3" 
 }

等等......动态类型中的列数也可以变化。列数可以或多或少。

现在,如果我想在这个 IEnumerable 集合中搜索 somevalue2,我需要在“column2”列的第 2 行(假设 column1 始终是主键)中找到以下信息。这将是将此动态集合转换为数据结构(.NET 列表/集合/哈希表等)的最佳方式,也是从集合中查询信息的最佳方式。该集合最多将是一页数据(25 行)。任何能够以超快速有效的方式搜索数据的代码片段和数据结构都将不胜感激。假设搜索词是“包含”匹配而不是完美匹配。

4

3 回答 3

4

这些是匿名类型;匿名类型是一种编译器特性,因此布局在编译时是固定不变的,因此它们不会发生变化。我建议:不要使用dynamic. 例如:

 var arr = new[] {
   new { column1 = "1", column2 = "name", column3= "somevalue" }, 
   new { column1 = "2", column2 = "name2", column3= "somevalue2" },
   new { column1 = "3", column2 = "name3", column3= "somevalue3" }
 };

这都是强类型和明确定义的。您可以使用常规操作,例如:

var item2 = arr.FirstOrDefault(x => x.column1 == "2");

再次,所有静态类型。

如果你想搜索所有的列,那么我建议像字典这样的东西更好:

 var arr = new[] {
   new Dictionary<string,string> { {"column1", "1"}, ... }, 
   new Dictionary<string,string> { {"column1", "2"}, ... }, 
   new Dictionary<string,string> { {"column1", "3"}, ... }, 
 };

既然你可以看看.Values.Contains(...)


编辑:有了评论,我我更清楚地理解它;我正在描绘一个不透明的方法,它返回IEnumerable<dynamic>实际上是 POCO 类型(不是动态类型),我们想要检查字符串成员(任意名称)是否匹配。我们应该能够通过反射来做到这一点,但FastMember会使其更快:

static void Main()
{
    string search = "ame2";

    int rowIndex = 0;
    string[] names = null;
    TypeAccessor accessor = null;
    foreach(object row in GetData())
    {
        if(names == null)
        { // first row; get the property-names and build an accessor
            names = (from prop in row.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
                     where prop.PropertyType == typeof (string)
                     select prop.Name).ToArray();
            accessor = TypeAccessor.Create(row.GetType());
        }

        foreach(var name in names)
        {
            var val = accessor[row, name] as string;
            if(val != null && val.Contains(search))
            {
                Console.WriteLine("row {0}, col {1}, val {2}", rowIndex, name, val);
            }
        }
        rowIndex++;
    }
}
static IEnumerable<dynamic> GetData()
{
    yield return new {column1 = "1", column2 = "name", column3 = "somevalue"};
    yield return new {column1 = "2", column2 = "name2", column3 = "somevalue2"};
    yield return new {column1 = "3", column2 = "name3", column3 = "somevalue3"};
}
于 2012-08-07T19:51:14.583 回答
0

如果您真的希望它们成为每个项目中具有不同列的动态对象,则可以这样声明:

IEnumerable<dynamic> collection = new dynamic[]
                                        {
                                            new  
                                                {
                                                    column1 = "1",
                                                    column2 = "name",
                                                    column3 = "somevalue"
                                                },
                                            new
                                                {
                                                    column1 = "2",
                                                    column2 = "name2"
                                                },
                                            new
                                                {
                                                    column1 = "3",
                                                    column2 = "name3",
                                                    column3 = "somevalue3",
                                                    column4 = "fourthValue"
                                                }
                                        };

将其转换为列表很简单:

// create a list
var list = new List<dynamic>(collection);

由于属性可能不存在,因此查找项目有点复杂:

// find an item
var itemOne = collection.Where(i =>
                                    {
                                        try
                                        {
                                            if (i.column1 == "1")
                                            {
                                                return true;
                                            }
                                        }
                                        catch
                                        {
                                            // ignore error, column doesn't exist
                                        }
                                        return false;
                                    });
于 2012-08-07T19:54:09.120 回答
0

我不知道你的 IEnumerable 下到底隐藏了什么,但最近我不得不搜索 Dapper 从一些作为动态 IEnumerable 返回的查询返回的结果(这就是我遇到这个问题的方式)。

就我而言,解决方案是投我的

IEnumerable<dynamic>

作为

IEnumerable<IDictionary<String, Object>>

但我认为它只适用于通过 dapper 获取的数据,例如:

db.Connection.Query(myQuery)

对于这个特定的问题,这样的事情可能会起作用(尚未测试):

IEnumerable<IDictionary<String, Object>> data = YourData.Cast<IDictionary<String, Object>>();
var row = data.SingleOrDefault(x => x.Where(y => y.Value.ToString() == "somevalue2"));

我不知道这项工作的速度有多快,但我希望它能帮助你(或某人,看到这个问题是不久前发布的)。

于 2014-02-06T09:43:28.680 回答