检索作为对象传递的HashSet属性

本文关键字:HashSet 属性 对象 检索 | 更新日期: 2023-09-27 18:14:25

我正在维护一个应用程序的一部分,该应用程序将实体框架实体作为对象,并返回其所有属性和相应值的列表。

方法看起来像这样:

public static List<string> ExtractAttributes(object data)
{
    List<string> attributes = new List<string>();
    foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(data))
    {
        Console.WriteLine("Name: {0}  Value: {1}  Type: {2}", property.Name, property.GetValue(data), data.GetType());
        attributes.Add(property.Name);
    }
    return attributes;
}

使用以下对象调用此方法:

ExtractAttributes(HashSet<Dog> dogs);

方法返回Count和Comparer (HashSet的属性),而不是Dog的属性。因此,有必要将data对象转换为哈希集集合的第一个对象(它只需要是集合中的第一个对象,原因太长,无法详细解释)。

我为此编写的代码如下:
public static List<String> ExtractAttributes(object data)
{
...
if (data.GetType().IsGenericType &&
    data.GetType().GetGenericTypeDefinition() == typeof(HashSet<>))
{
    List<object> hashSetAsList = new List<object>((IEnumerable<object>)data);
    if (hashSetAsList.Count > 0)
    {
        data = hashSetAsList[0];
    }
}
...
}

是否有任何方法来改善这个丑陋的代码给定的约束是无法改变任何其他的方法/返回类型?

编辑ExtractAttributes方法是递归的(在某种程度上取决于某些外部XML的逻辑),但可以表示为:

foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(data))
{
    Console.WriteLine("Name: {0}  Value: {1}  Type: {2}", property.Name, property.GetValue(data), data.GetType());
    if (property.GetValue(data).GetType().IsGenericType)
    {
        attributes.AddRange(ExtractAttributes(property.GetValue(data)));
    }
}

检索作为对象传递的HashSet属性

您可以更一般地检查它,尝试将对象强制转换为简单的非泛型IEnumerable

public static List<String> ExtractAttributes(object data) {
    ...
    if (data is IEnumerable) {
        var enumerator = ((IEnumerable)data).GetEnumerator();
        if (enumerator.MoveNext() && enumerator.Current != null) {
            data = enumerator.Current;
        }
    }
    ...
}

如果你真的只想对哈希集做这个,我想你可以添加你的标准来检查哈希集:

if (data is IEnumerable &&
    data.GetType().IsGenericType &&
    data.GetType().GetGenericTypeDefinition() == typeof(HashSet<>)) {

您可以考虑创建一个超载的ExtractAttributes方法来接受,比如说,IEnumerable<object>。这样,在传递HashSet时将选择更具体的重载。

我猜你可以直接转换HashSet并取第一个元素

HashSet<object> castedObject = Object as HashSet<object>;
object first = castedObject != null ? castedObject.First() : "";