Reputation: 65
I have a requirement to convert an internal type to a list of generic name/value pairs. This is so we can send out a lot of information in a general/standard way without worrying about changing schemas etc. if a new field is added. My issue is how to populate the generic structure.
For example an internal bunch of fields:
[Serializable]
public class Location
{
public string sAddress { get; set; }
public string sCity { get; set; }
public int iZipCode { get; set; }
}
Needs to be transformed into:
<AttributeList>
<Attribute>
<Name>sAddress</Name>
<Value>123 ABC Street</Value>
<DataType>string</DataType>
</Attribute>
</AttributeList>
Repeat for sCity and iZipCode.
Only I am not sure the best way to do this, as some of the fields, e.g. iZipCode may not be instantiated.
The only way I can think of is to have code looking for each specific field in the internal data structure, making sure it is not null, then mapping the Attribute.Name from a enum object (or something) that contains the actual internal field name (like sAddress), then the value, and then setting the type as I know what type if field that is as I am looking for it specifically.
This is fine if there are only 3 fields, but there will be far more than that, and it seems like a bad approach, as if a new field is added I need to update the code – not to mention a lot of code that is basically doing the same thing.
Ideally I would like something that can generically cycle through everything in the internal structure, e.g. Location, and automatically check if the field is there, pulling the name of the field, value and type if it is without having specific code for each field.
I don’t know if this is possible, any advice would be appreciated!
Upvotes: 0
Views: 206
Reputation: 19496
This will spit your example out into XML. You'll need to do some additional work if you want to support indexed properties:
Location loc = new Location { sAddress = "123 ABC Street",
sCity = "Fake City",
iZipCode = 12345 };
XDocument doc = new XDocument();
XElement attrList = new XElement("AttributeList");
doc.Add(attrList);
foreach (PropertyInfo propInfo in loc.GetType().GetProperties())
{
XElement attrRoot = new XElement("Attribute", new XElement("Name") { Value = propInfo.Name });
object propValue = propInfo.GetValue(loc, null);
attrRoot.Add(new XElement("Value") { Value = propValue == null ? "null" : propValue.ToString() });
attrRoot.Add(new XElement("DataType") { Value = propInfo.PropertyType.ToString() });
attrList.Add(attrRoot);
}
Upvotes: 1
Reputation: 516
You can do this with reflection. Here's an example:
PropertyInfo[] properties
properties = typeof(Location).GetProperties(BindingFlags.Public);
StringBuilder sb = new StringBuilder()
foreach (PropertyInfo p in properties)
{
sb.Append(p.Name)
sb.Append(p.PropertyType)
sb.Append(p.GetValue(null,null))
}
Obviously change the formatting so it suits you.
You'll need to use the System.Reflection namespace.
EDIT: I just saw your edits and that you want the output as XML. It may be worth looking at XML Serialisation as well.
Upvotes: 1