Click here to Skip to main content
15,878,945 members
Articles / Web Development / IIS

Build ReST based Web Services in .NET/C#

Rate me:
Please Sign up or sign in to vote.
5.00/5 (12 votes)
12 Jul 2009CPOL2 min read 122.2K   5.5K   55  
A ReST based Web Service for C#.
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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
Loves coding...

Comments and Discussions