PropertyInfo: Determine if and object contain another object

M

michelqa

I'm working on a custom xml serializer to store property information
of System.Windows.Forms.control object. For my testing I use a
ListView items object and try to get all object and properties-
collection contained in listView1.Items. My problem is the following:

I dont know how to tell if an object contain a "child" object. By
Example listView1.Font contains child object/properties like
"listView1.Font.Name" , "listView1.Font.Size" , ...

I already figure out how to manage the indexes when
p.GetIndexParameters().Length > 0
I stripped my code to show want I need to do.

//Note object is listView1.Items
using System.Reflection;
private static string SerializeObjectRecursive(object obj)
{
string XmlString="";
// ....
PropertyInfo[] PI=obj.GetType().GetProperties();
foreach (PropertyInfo pi in PI)
{
object MyObject=pi.GetValue(obj,null)
MessageBox.Show("I want to know if MyObject
contain other child object");
// If(MyObject== contain other child objects)
// XmlString += SerializeObjectRecursive
(MyObject);
// else
// XmlString +="<"+pi.Name+">"+
MyObject.ToString()+"</"+pi.Name+">";
}
// ....
return XmlString;
}

Thanks
 
J

Josh Einstein

You should start by creating a list of types that your serializer will treat
as "simple" types - that is, strings, dates, integers, etc can all be
serialized using native XML types. You might find some useful functions in
the XmlConvert class.

Then for all other types that are not simple types (which you need to define
manually) treat them as complex types and pass them into a function that
does a memberwise serialization. For any one of these members, you will
check whether it's a simple/complex type and recursively serialize that
member. You have to use recursion. The same function that serializes your
ListViewItem should be the one that serializes the Font object.

Now here's the thing - you can make your XML more readable and avoid
potential problems with read-only, write-once, etc fields if you use the XML
serializer for things that CAN be serialized. Also check out the
SoapFormatter.

There's a 101 ways to do what you're trying to do but they're all pretty
complicated. I won't even get into the problem of tracking object references
(for example, you have two TreeViewItems that both have the same Parent
node...)

Josh Einstein
 
M

michelqa

Thanks again for your advises

How can I test if an object is a complex Type?


The only problem I have is to determine if the property is a
string,int,etc... or another "child" object like listView1.Font.

The only way to do that is to check the objec type with "Known" type
like this

switch(p.PropertyType.ToString())
{
case "System.String":
case "System.Int32":
case "....":
// just serialize the value

defaut:
// this is a complex object must call SerializeObjectRecursive
() with this object

}

But there are a lot of type possibilities, this not seems to be a good
approach.

Im working now to see if this can be determined with the XMLSerializer
instead... if the object cannot be serialized this is a complex object
and will parse the child object until XmlSerializer can serialize it
but again this not seems to be a good approach too.


My complete function look like this :
private static string newSerializeObjectRecursive(object obj)
{
string XmlString="";
PropertyInfo[] PI=obj.GetType().GetProperties();
foreach (PropertyInfo p in PI)
{
try
{
if (p.GetIndexParameters().Length > 0) //Indexed object
{
ParameterInfo[] indexes = p.GetIndexParameters();
bool ParsingIndex=true;
int IndexCnt=0;
while(ParsingIndex)
{
try
{
object[] indexValues = {IndexCnt};
object CurrentObj=p.GetValue(obj, indexValues);
XmlString+="<"+p.Name+" Type=\""+p.PropertyType.ToString()+"\">";
XmlString+=CurrentObj.ToString();
XmlString+=SerializeObjectRecursive(p.GetValue(obj,
indexValues));
XmlString+="</"+p.Name+">";
}
catch
{ // Cannot read more item by index
break;
}
IndexCnt++;
}
}
else
{
// the following If
statement is incorrect to test if the object is simple or complex
if (p.PropertyType.ToString()==p.GetValue(obj,null).ToString())
{
XmlString+="<"+p.Name+" Type=\""+p.PropertyType.ToString()
+"\">"+p.GetValue(obj,null).ToString();
XmlString+=SerializeObjectRecursive(p.GetValue(obj,null));
XmlString+="</"+p.Name+">";
}
else
{
XmlString+="<"+p.Name+" Type=\""+p.PropertyType.ToString()+"\">";
XmlString+=p.GetValue(obj,null).ToString();
XmlString+="</"+p.Name+">";
}
}
}
catch{ //dont care}
}
return XmlString;
}

At least it can parse complicate objects but of course the value of
the property is not always the object the object type in text for most
object :( (see last if statement) What is the correct way to do this?
 
M

michelqa

Solved

In the last if I add several type conditions for special cases and
seems like it is working now :)

Not the cleanest solution but it work , I'm totally out of schedule on
the project and I dont have time to work more on this.

Thanks again Josh your help was really appreciated. Sometime we just
need an overview of the possibilities by an expert to choose the right
solution to solve the problem.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top