I have implemented an IDataContractSurrogate to enable serialization of ImmutableList<T> (from the Microsoft Immutable Collections BCL)  using the DataContractSerialization framework.The code is a bit wild using reflection and compiling of delegates. Are there any subtle improvements or obvious over engineering problems here?This is a follow-up from a Stack Overflow question, but further improvements feel like code review rather than specific questions.TESTCASEusing FluentAssertions;using System.Collections.Immutable;using System.IO;using System.Linq;using System.Runtime.Serialization;using System.Text;using System.Xml;using Xunit;namespace ReactiveUI.Ext.Spec{    [DataContract(Name=Node, Namespace=http://foo.com/)]    class Node    {        [DataMember()]        public string Name;    }    [DataContract(Name=Fixture, Namespace=http://foo.com/)]    class FixtureType    {        [DataMember()]        public ImmutableList<Node> Nodes;        public FixtureType(){            Nodes = ImmutableList<Node>.Empty.AddRange( new []            { new Node(){Name=A}            , new Node(){Name=B}            , new Node(){Name=C}            });        }    }    public class ImmutableSurrogateSpec    {          public static string ToXML(object obj)            {                var settings = new XmlWriterSettings { Indent = true };                using (MemoryStream memoryStream = new MemoryStream())                using (StreamReader reader = new StreamReader(memoryStream))                using (XmlWriter writer = XmlWriter.Create(memoryStream, settings))                {                    DataContractSerializer serializer =                      new DataContractSerializer                          ( obj.GetType()                          , new DataContractSerializerSettings() { DataContractSurrogate = new ImmutableSurrogateSerializer() }                          );                    serializer.WriteObject(writer, obj);                    writer.Flush();                    memoryStream.Position = 0;                    return reader.ReadToEnd();                }            }        public static T Load<T>(Stream data)        {            DataContractSerializer ser = new DataContractSerializer                  ( typeof(T)                  , new DataContractSerializerSettings() { DataContractSurrogate = new ImmutableSurrogateSerializer() }                  );            return (T)ser.ReadObject(data);        }        public static T Load<T>(string data)        {            using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(data)))            {                return Load<T>(stream);            }        }        [Fact]        public void ShouldWork()        {            var o = new FixtureType();            var s = ToXML(o);            var oo = Load<FixtureType>(s);            oo.Nodes.Count().Should().Be(3);            var names = oo.Nodes.Select(n => n.Name).ToList();            names.ShouldAllBeEquivalentTo(new[]{A, B, C});                        }    }}IMPLEMENTATIONusing System;using System.Collections.Concurrent;using System.Collections.Generic;using System.Collections.Immutable;using System.Linq;using System.Linq.Expressions;using System.Reflection;using System.Runtime.Serialization;namespace ReactiveUI.Ext{    class ImmutableListListConverter<T>    {        public static ImmutableList<T> ToImmutable( List<T> list )        {            return ImmutableList<T>.Empty.AddRange(list);        }        public static List<T> ToList(ImmutableList<T> list){            return list.ToList();        }        public static object ToImmutable( object list )        {            return ToImmutable(( List<T> ) list);        }        public static object ToList(object list){            return ToList(( ImmutableList<T> ) list);        }    }    static class ImmutableListListConverter {        static ConcurrentDictionary<Tuple<string, Type>, Func<object,object>> _MethodCache             = new ConcurrentDictionary<Tuple<string, Type>, Func<object,object>>();        public static Func<object,object> CreateMethod( string name, Type genericType )        {            var key = Tuple.Create(name, genericType);            if ( !_MethodCache.ContainsKey(key) )            {                _MethodCache[key] = typeof(ImmutableListListConverter<>)                    .MakeGenericType(new []{genericType})                    .GetMethod(name, new []{typeof(object)})                    .MakeLambda();            }            return _MethodCache[key];        }        public static Func<object,object> ToImmutableMethod( Type targetType )        {            return ImmutableListListConverter.CreateMethod(ToImmutable, targetType.GenericTypeArguments[0]);        }        public static Func<object,object> ToListMethod( Type targetType )        {            return ImmutableListListConverter.CreateMethod(ToList, targetType.GenericTypeArguments[0]);        }        private static Func<object,object> MakeLambda(this MethodInfo method )        {            return (Func<object,object>) method.CreateDelegate(Expression.GetDelegateType(            (from parameter in method.GetParameters() select parameter.ParameterType)            .Concat(new[] { method.ReturnType })            .ToArray()));        }       }    public class ImmutableSurrogateSerializer : IDataContractSurrogate    {        static ConcurrentDictionary<Type, Type> _TypeCache = new ConcurrentDictionary<Type, Type>();        public Type GetDataContractType( Type targetType )        {            if ( _TypeCache.ContainsKey(targetType) )            {                return _TypeCache[targetType];            }            if(targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(ImmutableList<>))             {                return _TypeCache[targetType]                     = typeof(List<>).MakeGenericType(targetType.GetGenericArguments());            }            else            {                return targetType;            }        }        public object GetDeserializedObject( object obj, Type targetType )        {            if ( _TypeCache.ContainsKey(targetType) )            {               return ImmutableListListConverter.ToImmutableMethod(targetType)(obj);            }            return obj;        }        public object GetObjectToSerialize( object obj, Type targetType )        {            if ( targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(ImmutableList<>) )            {               return ImmutableListListConverter.ToListMethod(targetType)(obj);            }            return obj;        }        public object GetCustomDataToExport( Type clrType, Type dataContractType )        {            throw new NotImplementedException();        }        public object GetCustomDataToExport( System.Reflection.MemberInfo memberInfo, Type dataContractType )        {            throw new NotImplementedException();        }        public void GetKnownCustomDataTypes( System.Collections.ObjectModel.Collection<Type> customDataTypes )        {            throw new NotImplementedException();        }        public Type GetReferencedTypeOnImport( string typeName, string typeNamespace, object customData )        {            throw new NotImplementedException();        }        public System.CodeDom.CodeTypeDeclaration ProcessImportedType( System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit )        {            throw new NotImplementedException();        }        public ImmutableSurrogateSerializer() { }    }}
Improve this reflection bashing code
c#;reflection;serialization