C# 关于列表和打印值的思考

C# 关于列表和打印值的思考,c#,reflection,C#,Reflection,我编写了一个方法,它接受一个泛型参数,然后打印它的属性。我用它来测试我的web服务。它正在工作,但我想添加一些我不知道如何实现的功能。我想打印列表的值,因为现在它只写System.Collection.Generic.List1,这是预期的 这是我到目前为止的代码,它适用于基本类型(int、double等): 静态void printReturnedProperties(T对象) { PropertyInfo[]propertyInfos=null; propertyInfos=Object.

我编写了一个方法,它接受一个泛型参数,然后打印它的属性。我用它来测试我的web服务。它正在工作,但我想添加一些我不知道如何实现的功能。我想打印列表的值,因为现在它只写System.Collection.Generic.List1,这是预期的

这是我到目前为止的代码,它适用于基本类型(int、double等):

静态void printReturnedProperties(T对象)
{ 
PropertyInfo[]propertyInfos=null;
propertyInfos=Object.GetType().GetProperties();
foreach(propertyInfos中的var项目)
Console.WriteLine(item.Name+”:“+item.GetValue(Object.ToString());
}

可以通过索引器属性
检索列表中的元素。此属性接受索引参数(有一个重载
PropertyInfo.GetValue
,它接受
对象
数组,就像
MethodInfo.Invoke
)并返回该位置的对象

int index = /* the index you want to get here */;
PropertyInfo indexer = Object.GetProperty("Item");
object item = indexer.GetValue(Object, new object[] { index });

我通常在每个项目之间打印带有
的列表

为了方便起见,我创建了一个简单的扩展方法:

public static class ListEx
{
    public static string StringJoin<T>(this IEnumerable<T> items)
    {
        return string.Join(", ", items);
    }
}
公共静态类ListEx
{
公共静态字符串StringJoin(此IEnumerable items)
{
返回字符串。Join(“,”,items);
}
}
将该方法调用为
myList.StringJoin()


当然,您可以修改该方法以使用另一个分隔符och调用
字符串。直接加入

您可以执行以下操作:

    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());
                }
            }
        }


    }
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并打印出各个值(我每行打印一个值,但显然,您可以执行不同的操作。)

这里是一个片段,假设您的列表类型为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());

                }
foreach(propertyInfos中的PropertyInfo项)
{
Object obj=item.GetValue(Object,null);
如果(!obj.GetType().IsValueType)
{
if(obj.GetType()==typeof(字符串))
{
Console.WriteLine(obj.ToString());
}
else if(obj.GetType()==typeof(List))
{
//运行循环并打印列表
}
else if(obj.GetType().IsArray)//这表示它的数组
{
//运行循环以打印阵列
}
}
其他的
{
//它是原语,所以我们将转换为字符串
Console.WriteLine(obj.ToString());
}

我想你想要这样的东西:

    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());
                }
            }
        }


    }
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);
    }
}
公共类程序
{
公共静态无效打印属性(T)
{
var properties=t.GetType().GetProperties();
foreach(属性中的var属性)
{
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()将获取列表的基础类型,
//即,您当前所在的属性的类型
//处理类型为IEnumerable
formatList.MakeGenericMethod(value.GetType().GetGenericArguments().First());
value=formatList.Invoke(null,新对象[]{value});
Console.Out.WriteLine(名称+“:”+值);
}
其他的
{
Console.Out.WriteLine(名称+“:”+值);
}
}
}
公共静态字符串格式列表(IEnumerable l)
{
返回字符串。Join(“,”,l);
}
}
代码未经测试,但基本上,与标量值相比,您希望以不同的方式处理可枚举类型,因此,一旦遇到类型为
IEnumerable
的内容,您就可以调用
FormatList
方法

现在,请记住,您原来的
T
TItemType
不一定相同。当您使用反射调用FormatList时,您希望将
TPlaceholder
绑定到
TItemType
。一旦这样做,您只需调用格式化方法并将列表的实际实例传递给它,该实例将给你一个字符串,然后你就可以输出这个字符串了


希望这能有所帮助。

大量借用上述示例,这是我的完整解决方案。这已经过测试,并通过打印每个元素的属性来处理IEnumerable的传入。它不是递归的,但添加起来很容易

请注意,上面的许多示例都会因索引属性(例如列表)而崩溃。

这里通过使用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();
    }
//
///返回对象属性状态的字符串表示形式,即名称:Jim,年龄:43
/// 
公共静态字符串GetPropertyStateList(此对象obj)
{
如果(obj==null)返回“objectnull”;
var sb=新的StringBuilder();
var enumerable=对象作为IEnumerable;
if(可枚举!=null)
{
foreach(可枚举中的var listitem)
{
(某人);
sb.追加(ReadProperties(listitem));
}
}
其他的
{
sb.Append(ReadProperties(obj));
}
使某人返回字符串();
}
私有静态字符串读取属性(对象obj)
{
var sb=新的StringBuilder();
var propertyInfos=obj.GetType().GetProperties().OrderBy(x=>x.Name).Where(x=>!x.GetIndexParameters().Any());
foreach(不动产中的var prop YNFOS)
{