我写了一个接受泛型参数然后打印其属性的方法。我用它来测试我的网络服务。它正在工作,但我想添加一些我不知道如何实现的功能。我想打印列表的值,因为它现在只写了预期的System.Collection.Generic.List1。
到目前为止,这是我的代码,这适用于基本类型(int,double等):
static void printReturnedProperties<T>(T Object)
{
PropertyInfo[] propertyInfos = null;
propertyInfos = Object.GetType().GetProperties();
foreach (var item in propertyInfos)
Console.WriteLine(item.Name + ": " + item.GetValue(Object).ToString());
}
答案 0 :(得分:7)
你可以这样做:
static void printReturnedProperties(Object o)
{
PropertyInfo[] propertyInfos = null;
propertyInfos = o.GetType().GetProperties();
foreach (var item in propertyInfos)
{
var prop = item.GetValue(o);
if(prop == null)
{
Console.WriteLine(item.Name + ": NULL");
}
else
{
Console.WriteLine(item.Name + ": " + prop.ToString());
}
if (prop is IEnumerable)
{
foreach (var listitem in prop as IEnumerable)
{
Console.WriteLine("Item: " + listitem.ToString());
}
}
}
}
然后它将枚举任何IEnumerable并打印出各个值(我每行打印一个,但很明显,你可以做不同的。)
答案 1 :(得分:3)
可以通过索引器属性Item
检索列表中的元素。此属性接受一个索引参数(有PropertyInfo.GetValue
的重载接受object
数组,就像MethodInfo.Invoke
一样)并返回该位置的对象。
int index = /* the index you want to get here */;
PropertyInfo indexer = Object.GetProperty("Item");
object item = indexer.GetValue(Object, new object[] { index });
答案 2 :(得分:2)
我通常在每个项目之间打印一个,
的列表。
为了方便起见,我创建了一个简单的扩展方法:
public static class ListEx
{
public static string StringJoin<T>(this IEnumerable<T> items)
{
return string.Join(", ", items);
}
}
将方法调用为myList.StringJoin()
。
您当然可以修改方法以直接使用另一个分隔符och call string.Join
。
答案 3 :(得分:1)
这是一个片段,假设您的列表是T型。
foreach (PropertyInfo item in propertyInfos)
{
Object obj = item.GetValue(object,null);
if (!obj.GetType().IsValueType)
{
if (obj.GetType() == typeof(String))
{
Console.WriteLine(obj.ToString());
}
else if (obj.GetType() == typeof(List<T>))
{
//run a loop and print the list
}
else if (obj.GetType().IsArray) // this means its Array
{
//run a loop to print the array
}
}
else
{
//its primitive so we will convert to string
Console.WriteLine(obj.ToString());
}
答案 4 :(得分:1)
我想你想要这样的东西:
public class Program
{
public static void PrintProperties<T>(T t)
{
var properties = t.GetType().GetProperties();
foreach (var property in properties)
{
var name = property.Name;
var value = property.GetValue(t, null);
if (property.PropertyType.IsGenericType && property.PropertyType == typeof(IEnumerable<>))
{
var formatList = typeof(Program).GetMethod("FormatList", new[] { value.GetType() });
// value.GetType().GetGenericArguments().First() will get you the underlying type of the list,
// i.e., the TItemType where the property you are currently
// handling is of type IEnumerable<TItemType>
formatList.MakeGenericMethod(value.GetType().GetGenericArguments().First());
value = formatList.Invoke(null, new object[] { value });
Console.Out.WriteLine(name + ": " + value);
}
else
{
Console.Out.WriteLine(name + ": " + value);
}
}
}
public static string FormatList<TPlaceholder>(IEnumerable<TPlaceholder> l)
{
return string.Join(", ", l);
}
}
代码未经测试但基本上,与标量值相比,您希望以不同方式处理可枚举类型,因此一旦您点击IEnumerable<TItemType>
类型的某些内容,就会调用FormatList<TPlaceholder>
方法。
现在,请记住,您原来的T
和TItemType
不一定相同。使用反射调用FormatList时,您希望将TPlaceholder
绑定到TItemType
。完成后,您只需调用格式化方法并将其传递给列表的实际实例,该实例将返回一个字符串。那个字符串就可以输出了。
希望有所帮助。
答案 5 :(得分:0)
在上面的例子中大量借鉴,这是我的完整解决方案。这已经过测试,并通过打印出每个元素的属性来处理传入的IEnumerable。它不是递归的,但这很容易添加。
请注意,上述许多示例都会因索引属性(例如列表)而崩溃。 Parameter count mismatch in property.GetValue()
通过使用LINQ的这一位过滤具有索引属性的属性,可以避免这种情况。
Where(x=>!x.GetIndexParameters().Any())
以下扩展方法形式的完整示例。
/// <summary>
/// Returns string representation of object property states i.e. Name: Jim, Age: 43
/// </summary>
public static string GetPropertyStateList(this object obj)
{
if (obj == null) return "Object null";
var sb = new StringBuilder();
var enumerable = obj as IEnumerable;
if (enumerable != null)
{
foreach (var listitem in enumerable)
{
sb.AppendLine();
sb.Append(ReadProperties(listitem));
}
}
else
{
sb.Append(ReadProperties(obj));
}
return sb.ToString();
}
private static string ReadProperties(object obj)
{
var sb = new StringBuilder();
var propertyInfos = obj.GetType().GetProperties().OrderBy(x => x.Name).Where(x=>!x.GetIndexParameters().Any());
foreach (var prop in propertyInfos)
{
var value = prop.GetValue(obj, null) ?? "(null)";
sb.AppendLine(prop.Name + ": " + value);
}
return sb.ToString();
}