问题
I wonder if anyone can help me - I've not done much with reflection but understand the basic principles.
What I'm trying to do:
I'm in the process of developing a class that gathers a lot of information about the local system, network, etc... to be used for automated bug reporting. Instead of having to change my test harness every time I add a new property, I'd (ideally) like to be able to serialise the lot as an XML string and just display that in a textbox.
Unfortunately, the Framework won't use the default XML serializer on read-only properties (which almost all of mine are) as they wouldn't deserialize properly
[Not sure I agree with the assumption that anything serialized must be de-serializable - MS says this is a feature "by design" which I suppose I can understand - Perhaps a tag to indicate that it should be serialized anyway would be advantageous?]
The initial approach was to make properties gettable and settable (with a throw exception on the setter) but the amount of work tidying this up afterwards seems a little excessive and I would want the properties to be read-only in the final version.
What I need help with:
My current plan is to use reflection to recursively iterate through each (public) property of my topmost gathering class. The problem is, the samples I've seen don't handle things recursively. Additionally, I only want to inspect an object's properties if it's in one of my assemblies - Otherwise just call .ToString on it.
If I don't have the inspection limited to my assembly, I assume I'll get (say) a string which then contains a Length which in turn will have .Tostring method...
For the purposes of this project, I can almost guarantee no circular references within my code and as this will only be used as a development tool so I'm not too concerned about it running amok now and then.
I'd appreciate some examples/advice.
Many thanks in advance.
回答1:
This will hopefully get you started. It prints a tree directly to the console so you'll need to adjust to output XML. Then change the IsMyOwnType method to filter out the assemblies you're interested in, right now it only cares about types in the same assembly as itself.
Shared Sub RecurseProperties(o As Object, level As Integer)
For Each pi As PropertyInfo In o.GetType().GetProperties()
If pi.GetIndexParameters().Length > 0 Then Continue For
Console.Write(New String(" "c, 2 * level))
Console.Write(pi.Name)
Console.Write(" = ")
Dim propValue As Object = pi.GetValue(o, Nothing)
If propValue Is Nothing Then
Console.WriteLine("<null>")
Else
If IsMyOwnType(pi.PropertyType) Then
Console.WriteLine("<object>")
RecurseProperties(propValue, level+1)
Else
Console.WriteLine(propValue.ToString())
End If
End If
Next
End Sub
Shared Function IsMyOwnType(t As Type) As Boolean
Return t.Assembly Is Assembly.GetExecutingAssembly()
End Function
回答2:
you extension version on c# to use on any object
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace Extensions
{
public static class ObjectExtension
{
public static string ToStringProperties(this object o)
{
return o.ToStringProperties(0);
}
public static string ToStringProperties(this object o, int level)
{
StringBuilder sb = new StringBuilder();
string spacer = new String(' ', 2 * level);
if (level == 0) sb.Append(o.ToString());
sb.Append(spacer);
sb.Append("{\r\n");
foreach (PropertyInfo pi in o.GetType().GetProperties())
{
if (pi.GetIndexParameters().Length == 0)
{
sb.Append(spacer);
sb.Append(" ");
sb.Append(pi.Name);
sb.Append(" = ");
object propValue = pi.GetValue(o, null);
if (propValue == null)
{
sb.Append(" <null>");
} else {
if (IsMyOwnType(pi.PropertyType))
{
sb.Append("\r\n");
sb.Append(((object)propValue).ToStringProperties(level + 1));
} else{
sb.Append(propValue.ToString());
}
}
sb.Append("\r\n");
}
}
sb.Append(spacer);
sb.Append("}\r\n");
return sb.ToString();
}
private static bool IsMyOwnType(Type t)
{
return (t.Assembly == Assembly.GetExecutingAssembly());
}
}
}
来源:https://stackoverflow.com/questions/1410807/reflection-iterate-objects-properties-recursively-within-my-own-assemblies-v