views:

1047

answers:

1

Hi,

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.

+2  A: 

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
Mattias S
I've been hammering away at something similar and ended up with something that works but was spaghetti code. Your example is far more concise and a great help - Many thanks
Basiclife
Of course, my next problem is enumerating lists... Again, I've found a way to do it but it's currently a mess. If/when I get the code in a presentable state, I'll post the final version.
Basiclife