从IEnumerable <unknowntype> </unknowntype>中选择新的{Unknown fields}

时间:2013-12-29 03:53:06

标签: c# linq reflection datagridview expression

我正在使用VS2010和EF4.0。目标是选择任何IEnumerable的字段,以便在DataGridView中显示。以 Northwind.Employees 为例,以下代码没问题。

private void button1_Click(object sender, EventArgs e)
{
    NorthwindEntities en = new NorthwindEntities();
    dataGridView1.DataSource = SelectNew(en.Employees, new string[] { "EmployeeID", "FirstName" });
}

public object SelectNew(object items, string[] fields)
{
    IEnumerable<Employee> ems = items as IEnumerable<Employee>;
    return ems.Select(em => new
    {
        id = em.EmployeeID,
        name = em.FirstName
    }
    ).ToArray();
}

参数对象项 EntityObject的IEnumerable ,该函数将在客户端存储器中执行,现在与数据库无关。
但我在运行时之前不知道EntityObject类型(Employee),因此可能会使用一些复杂的反射。
我查了this, 但是当我将结果绑定到控件时,它只显示没有任何列或数据的空行。并且功能用于IQueryable ,我尝试过IEnumerable.AsQueryable并传递给它,但结果也没有显示任何列。

1 个答案:

答案 0 :(得分:1)

我修改了上面评论中指出的例子。这实际上返回IEnumerable<Dictionary<string,object>>,其中每个Dictionary代表一个“新对象”,字典中的每个键值对代表一个属性及其值。也许您可以修改它以供您使用?

我不确定你是否可以简单地将结果绑定到DataGrid,但你应该能够弄明白。

我不相信可以动态创建匿名类型......但是可以将其更改为使用动态类型,如ExpandoObject而不是词典。有关如何执行此操作的一些提示,请参阅this question。我从来没有使用动态物体,所以你自己就在那里!

public class TestClassA {
    public string SomeString { get; set; }

    public int SomeInt { get; set; }

    public TestClassB ClassB { get; set; }
}

public class TestClassB {
    public string AnotherString { get; set; }
}

public class Program {

    private static void Main(string[] args) {
        var items = new List<TestClassA>();
        for (int i = 0; i < 9; i++) {
            items.Add(new TestClassA {
                SomeString = string.Format("This is outer string {0}", i),
                SomeInt = i,
                ClassB = new TestClassB { AnotherString = string.Format("This is inner string {0}", i) }
            });
        }

        var newEnumerable = SelectNew(items, new string[] { "ClassB.AnotherString" });
        foreach (var dict in newEnumerable) {
            foreach (var key in dict.Keys)
                Console.WriteLine("{0}: {1}", key, dict[key]);
        }

        Console.ReadLine();
    }

    public static IEnumerable<Dictionary<string, object>> SelectNew<T>(IEnumerable<T> items, string[] fields) {
        var newItems = new List<Dictionary<string, object>>();
        foreach (var item in items) {
            var dict = new Dictionary<string, object>();
            foreach (var field in fields)
                dict[field] = GetPropertyValue(field, item);
            newItems.Add(dict);
        }
        return newItems;
    }

    private static object GetPropertyValue(string property, object o) {
        if (property == null)
            throw new ArgumentNullException("property");
        if (o == null)
            throw new ArgumentNullException("o");

        Type type = o.GetType();

        string[] propPath = property.Split('.');
        var propInfo = type.GetProperty(propPath[0]);

        if (propInfo == null)
            throw new Exception(String.Format("Could not find property '{0}' on type {1}.", propPath[0], type.FullName));

        object value = propInfo.GetValue(o, null);

        if (propPath.Length > 1)
            return GetPropertyValue(string.Join(".", propPath, 1, propPath.Length - 1), value);
        else
            return value;
    }
}