1

扩展方法将对象属性映射到 IDictionary 的最有效方法是什么:

  • 键是属性路径(例如“Customer.Company.Address.Line1”)
  • values 是属性值的字符串表示形式(例如“123 Main St.”或“”(空字符串),当为 null 或默认值时)
  • 属性集合仍然只包含路径(例如公共 IList Invoices --> "Customer.Invoices" 但值是集合计数)

使用反射是最好的方法吗?有例子吗?

谢谢Z...

澄清更新

  • 字典键应该是基于属性名称而不是类型层次结构的路径。因此,如果客户有属性public Company ParentCompany而公司有属性,public Address BillingAddress那么键路径应该是“ParentCompany.BillingAddress”
4

1 回答 1

2

编辑:

public static IDictionary<string, string> GetProperties<T>(this T obj)
    where T : class
{
    var properties = obj.GetPropertyList();
    return properties.ToDictionary(prop => prop.Item1, prop => prop.Item2);
}

public static IEnumerable<Tuple<string, string>> GetPropertyList<T>(this T obj)
    where T : class
{
    if (obj == null)
        throw new ArgumentNullException("obj");

    Type t = obj.GetType();

    return GetProperties(obj, t, t.Name);
}

private static IEnumerable<Tuple<string, string>> GetProperties(object obj, Type objType, string propertyPath)
{
    // If atomic property, return property value with path to property
    if (objType.IsValueType || objType.Equals(typeof(string)))
        return Enumerable.Repeat(Tuple.Create(propertyPath, obj.ToString()), 1);

    else
    {
        // Return empty value for null values
        if (obj == null)
            return Enumerable.Repeat(Tuple.Create(propertyPath, string.Empty), 1);

        else
        {
            // Recursively examine properties; add properties to property path
            return from prop in objType.GetProperties()
                   where prop.CanRead && !prop.GetIndexParameters().Any()
                   let propValue = prop.GetValue(obj, null)
                   let propType = prop.PropertyType
                   from nameValPair in GetProperties(propValue, propType, string.Format("{0}.{1}", propertyPath, prop.Name))
                   select nameValPair;
        }
    }
}

这仍然不能处理值参数的默认值。请注意,何时停止递归迭代的逻辑是关键。最初我停留在值类型的属性上,但这意味着字符串被视为其他对象。所以我添加了一个特殊情况来将字符串视为原子类型。

于 2012-06-07T16:21:56.653 回答