134 lines
3.7 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|