【问题标题】:C# Using Reflection to Get a Generic Object's (and its Nested Objects) PropertiesC# 使用反射获取通用对象(及其嵌套对象)的属性
【发布时间】:2011-02-24 02:22:55
【问题描述】:

这是为了帮助理解我想要实现的目标而创建的场景。

我正在尝试创建一个返回泛型对象的指定属性的方法

例如

public object getValue<TModel>(TModel item, string propertyName) where TModel : class{
    PropertyInfo p = typeof(TModel).GetProperty(propertyName);
    return p.GetValue(item, null);
}

如果您正在寻找TModel item 上的属性,上面的代码可以正常工作 例如

string customerName = getValue<Customer>(customer, "name");

但是,如果你想知道客户组的名字是什么,那就成了一个问题: 例如

string customerGroupName = getValue<Customer>(customer, "Group.name");

希望有人能给我一些关于这种出路方案的见解 - 谢谢。

【问题讨论】:

    标签: c# generics reflection properties types


    【解决方案1】:

    这是一个使用递归解决问题的简单方法。它允许您通过传递“带点”属性名称来遍历对象图。它适用于属性和字段。

    static class PropertyInspector 
    {
        public static object GetObjectProperty(object item,string property)
        {
            if (item == null)
                return null;
    
            int dotIdx = property.IndexOf('.');
    
            if (dotIdx > 0)
            {
                object obj = GetObjectProperty(item,property.Substring(0,dotIdx));
    
                return GetObjectProperty(obj,property.Substring(dotIdx+1));
            }
    
            PropertyInfo propInfo = null;
            Type objectType = item.GetType();
    
            while (propInfo == null && objectType != null)
            {
                propInfo = objectType.GetProperty(property, 
                          BindingFlags.Public 
                        | BindingFlags.Instance 
                        | BindingFlags.DeclaredOnly);
    
                objectType = objectType.BaseType;
            }
    
            if (propInfo != null)
                return propInfo.GetValue(item, null);
    
            FieldInfo fieldInfo = item.GetType().GetField(property, 
                          BindingFlags.Public | BindingFlags.Instance);
    
            if (fieldInfo != null)
                return fieldInfo.GetValue(item);
    
            return null;
        }
    }
    

    例子:

    class Person
    {
       public string Name { get; set; }
       public City City { get; set; }
    }
    
    class City
    {
       public string Name { get; set; }
       public string ZipCode { get; set; }
    }
    
    Person person = GetPerson(id);
    
    Console.WriteLine("Person name = {0}", 
          PropertyInspector.GetObjectProperty(person,"Name"));
    
    Console.WriteLine("Person city = {0}",
          PropertyInspector.GetObjectProperty(person,"City.Name"));
    

    【讨论】:

    • 非常感谢,这是一个值得学习的好作品,但是我已经接受了一个内置于 .NET 中的答案
    【解决方案2】:

    在 System.Web.UI 命名空间中有一种方法可以做到这一点:

    DataBinder.Eval(source, expression);
    

    【讨论】:

    • 好收获。我对这个唯一的“问题”是它依赖于 System.Web.dll
    • 是的,它可能应该去另一个程序集
    • 我很担心 - 为什么它在 System.Web.UI 中?
    • 我猜他们在带有 指令的 asp.net 模板控件中使用它,我对非 web .net 不是很熟悉,所以我不知道是否有另一种选择。
    【解决方案3】:

    我猜你只需要将其分解为几个步骤,而不是尝试一次性完成,例如:

    // First get the customer group Property...
    CustomerGroup customerGroup = getValue<Customer>(customer, "Group");
    // Then get the name of the group...
    if(customerGroup != null)
    {
        string customerGroupName = getValue<CustomerGroup>(customerGroup, "name");
    }
    

    【讨论】:

      【解决方案4】:

      由于 Group 是客户的财产,它本身承载财产名称,因此您也必须这样做。 但由于 '。'不能是属性名称的一部分,您可以轻松使用 String.Substring 从字符串中删除第一个属性名称并递归调用您的方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-29
        • 1970-01-01
        • 2022-10-14
        • 1970-01-01
        相关资源
        最近更新 更多