我维护一个应用程序的一部分,它将实体框架实体作为对象,并返回其所有属性和相应值的列表。
该方法如下所示:
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
对象转换为hashset集合的第一个对象(它只需要是集合中的第一个对象,原因太长,无法详细解释)。
我写的代码如下:
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)));
}
}
答案 0 :(得分:0)
您可以考虑创建ExtractAttributes
方法的重载,例如IEnumerable<object>
。这样,当您传递HashSet时,将选择更具体的重载。
答案 1 :(得分:0)
您可以更一般地检查它,尝试将对象转换为简单的非泛型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<>)) {
答案 2 :(得分:-1)
我猜你可以投出HashSet并获取第一个Element
HashSet<object> castedObject = Object as HashSet<object>;
object first = castedObject != null ? castedObject.First() : "";