|
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Collections;
using System.Globalization;
namespace PoC.Web.Services.Utilities
{
public class TypeConversion
{
private static IDictionary<Type, TypeConverter> customConverters;
static TypeConversion()
{
customConverters = new Dictionary<Type, TypeConverter>();
AddConverter(typeof(System.Xml.XmlDocument), new XmlDocumentConverter());
//TODO: Add for external converters...
}
public static void AddConverter(Type forType, TypeConverter conv)
{
//Assert.NotNull(forType, "forType");
//Assert.NotNull(conv, "conv");
customConverters.Add(forType, conv);
}
public static object ConvertType(string propName, object valueToSet, Type typeToSet)
{
if (valueToSet != null)
{
if (IsAssignableFrom(valueToSet, typeToSet))
{
return valueToSet;
}
if (typeToSet != null && typeToSet.IsArray)
{
Type componentType = typeToSet.GetElementType();
if (valueToSet is IList)
{
IList elements = (IList)valueToSet;
return ToArray(componentType, elements, propName);
}
else if (valueToSet is string)
{
if (typeToSet.Equals(typeof(char[])))
{
return ((string)valueToSet).ToCharArray();
}
else
{
string[] elements = GetStringList((string)valueToSet);
return ToArray(componentType, elements, propName);
}
}
else if (!valueToSet.GetType().IsArray)
{
Array result = Array.CreateInstance(componentType, 1);
object val = ConvertType(propName, valueToSet, componentType);
result.SetValue(val, 0);
return result;
}
}
#region Type Converter Factory
try
{
TypeConverter typeConverter = GetTypeConverter(typeToSet);
if (typeConverter != null && typeConverter.CanConvertFrom(valueToSet.GetType()))
{
try
{
valueToSet = typeConverter.ConvertFrom(valueToSet);
}
catch
{
if (valueToSet is string)
{
valueToSet = typeConverter.ConvertFromInvariantString((string)valueToSet);
}
}
}
else
{
typeConverter = GetTypeConverter(valueToSet.GetType());
if (typeConverter != null && typeConverter.CanConvertTo(typeToSet))
{
valueToSet = typeConverter.ConvertTo(valueToSet, typeToSet);
}
else if (customConverters.ContainsKey(typeToSet) && customConverters[typeToSet].CanConvertFrom(valueToSet.GetType()))
{
valueToSet = customConverters[typeToSet].ConvertFrom(valueToSet);
}
else
{
// finally look if it's an enum
if (typeToSet != null
&& typeToSet.IsEnum
&& (!(valueToSet is float)
&& (!(valueToSet is double))))
{
// convert numeric value into enum's underlying type
Type numericType = Enum.GetUnderlyingType(typeToSet);
valueToSet = System.Convert.ChangeType(valueToSet, numericType);
if (Enum.IsDefined(typeToSet, valueToSet))
{
valueToSet = Enum.ToObject(typeToSet, valueToSet);
}
else
{
throw new InvalidCastException(string.Format("Property [{0}] could not be set. Type mismatch detected.", propName));
}
}
else
{
throw new InvalidCastException(string.Format("Property [{0}] could not be set. Type mismatch detected.", propName));
}
}
}
}
catch (Exception ex)
{
throw new InvalidCastException(string.Format("Property [{0}] could not be set. Type mismatch detected.", propName), ex);
}
#endregion
if (valueToSet == null)
{
throw new InvalidCastException(string.Format("Property [{0}] could not be set. Type mismatch detected.", propName));
}
}
return valueToSet;
}
private static TypeConverter GetTypeConverter(Type type)
{
if (type == null) throw new ArgumentNullException("type");
//Assert.NotNull(type, "type");
TypeConverter converter = null;
if (converter == null)
{
if (type.IsEnum)
{
converter = new EnumConverter(type);
}
else
{
converter = TypeDescriptor.GetConverter(type);
}
}
return converter;
}
private static string[] GetStringList(string p)
{
return ToStringArray(p, ",");
}
public static string[] ToStringArray(string input, string delimiter)
{
if (input == null)
{
return new string[0];
}
if (string.IsNullOrEmpty(delimiter))
{
return new string[] { input };
}
return input.Split(delimiter[0]);
}
private static object ToArray(Type t, IList elem, string propName)
{
Array destination = Array.CreateInstance(t, elem.Count);
for (int i = 0; i < elem.Count; ++i)
{
object value = ConvertType(propName + "[" + i + "]", elem[i], t);
destination.SetValue(value, i);
}
return destination;
}
private static bool IsAssignableFrom(object newValue, Type requiredType)
{
if (newValue is MarshalByRefObject)
{
return true;
}
if (requiredType == null)
{
return false;
}
return requiredType.IsAssignableFrom(newValue.GetType());
}
public static GrafT Deserialize<GrafT>(System.IO.Stream stream)
{
System.Xml.Serialization.XmlSerializer deserializer = new System.Xml.Serialization.XmlSerializer(typeof(GrafT));
return (GrafT) deserializer.Deserialize(stream);
}
}
public class XmlDocumentConverter : TypeConverter
{
public override bool CanConvertFrom(
ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return TypeDescriptor.GetConverter(typeof(System.Xml.XmlDocument)).CanConvertFrom(context, sourceType);
//return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(
ITypeDescriptorContext context, CultureInfo culture, object value)
{
string xmlstr = value as string;
if (xmlstr != null)
{
System.Xml.XmlDocument dom = new System.Xml.XmlDocument();
if (xmlstr.Length > 0)
{
dom.LoadXml(xmlstr);
return dom;
}
}
return TypeDescriptor.GetConverter(typeof(System.Xml.XmlDocument)).ConvertFrom(context, culture, value);
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.