OpenLiveWriter/utilities/BlogServer/XmlRpc/XmlRpcSerializer.cs

134 lines
3.7 KiB
C#

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Reflection;
namespace BlogServer.XmlRpc
{
public class XmlRpcSerializer
{
public static object ToXmlRpc(object val)
{
if (val == null)
throw new ArgumentNullException("val");
if (val is int || val is bool || val is string || val is double || val is DateTime || val is byte[])
return val;
if (val is IDictionary)
{
IDictionary results = new HybridDictionary();
IDictionary dict = (IDictionary) val;
foreach (string key in dict.Keys)
{
results[key] = ToXmlRpc(dict[key]);
}
return results;
}
object[] attributes = val.GetType().GetCustomAttributes(typeof (XmlRpcSerializableAttribute), false);
if (attributes.Length > 0)
{
return ToDictionary(val);
}
if (val is IEnumerable)
{
ArrayList arrList = new ArrayList();
foreach (object o in (IEnumerable) val)
arrList.Add(ToXmlRpc(o));
return arrList.ToArray();
}
throw new ArgumentException("Unable to serialize object of type " + val.GetType().Name);
}
public static object FromXmlRpc(object val, Type desiredType)
{
if (desiredType.Equals(typeof(int))
|| desiredType.Equals(typeof(bool))
|| desiredType.Equals(typeof(string))
|| desiredType.Equals(typeof(double))
|| desiredType.Equals(typeof(DateTime))
|| desiredType.Equals(typeof(byte[]))
|| desiredType.Equals(typeof(object[])))
{
if (desiredType.IsInstanceOfType(val))
return val;
}
object[] attributes = desiredType.GetCustomAttributes(typeof (XmlRpcSerializableAttribute), false);
if (attributes.Length > 0)
{
return FromStruct((IDictionary) val, desiredType);
}
if (typeof(IDictionary).IsAssignableFrom(desiredType) && desiredType.IsInstanceOfType(val))
{
return val;
}
if (desiredType.IsArray)
{
object[] arr = (object[]) val;
Type elType = desiredType.GetElementType();
Array instance = Array.CreateInstance(elType, arr.Length);
for (int i = 0; i < arr.Length; i++)
instance.SetValue(arr[i], i);
return instance;
}
throw new ArgumentException("Cannot coerce type " + val.GetType().Name + " into " + desiredType.Name);
}
private static object FromStruct(IDictionary val, Type type)
{
object result = Activator.CreateInstance(type);
foreach (PropertyInfo prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
object[] attributes = prop.GetCustomAttributes(typeof (XmlRpcStructMemberAttribute), false);
if (attributes.Length > 0)
{
XmlRpcStructMemberAttribute attr = (XmlRpcStructMemberAttribute) attributes[0];
string name = attr.Name;
object propValue = val[name];
if (propValue != null)
{
Type propType = prop.PropertyType;
prop.SetValue(result, FromXmlRpc(propValue, propType), null);
}
}
}
return result;
}
private static IDictionary ToDictionary(object obj)
{
HybridDictionary results = new HybridDictionary();
foreach (PropertyInfo prop in obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
object[] attributes = prop.GetCustomAttributes(typeof (XmlRpcStructMemberAttribute), false);
if (attributes.Length > 0)
{
XmlRpcStructMemberAttribute attr = (XmlRpcStructMemberAttribute) attributes[0];
string name = attr.Name;
object val = prop.GetValue(obj, null);
if (val != null)
results[name] = ToXmlRpc(val);
}
}
return results;
}
private static Array ToArray(IEnumerable obj)
{
ArrayList results = new ArrayList();
foreach (object o in obj)
{
results.Add(ToXmlRpc(o));
}
return results.ToArray();
}
}
}