diff --git a/Changelog.txt b/Changelog.txt index 687720e..7c3fd59 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,6 +1,10 @@ ObjectSerialization =========================================== +Version 1.0.27 +------------------------------------------- ++ Optimized collections / arrays serialization by using generic methods of TypeSerializerFactory + Version 1.0.26 ------------------------------------------- + ensured proper and constant order of registered types with TypeInfoRepository.RegisterPredefinedUsingSerializableFrom diff --git a/ObjectSerialization.Performance/Program.cs b/ObjectSerialization.Performance/Program.cs index b2e3686..8950cae 100644 --- a/ObjectSerialization.Performance/Program.cs +++ b/ObjectSerialization.Performance/Program.cs @@ -15,11 +15,11 @@ class Program static void Main() { var monitor = new PerformanceMonitor( - new ObjectSerializerAdapter(), + new ObjectSerializerAdapter()/*, new BinaryFormatterAdapter(), new ProtoBufAdapter(), new NewtonBsonAdapter(), - new DataContractSerializerAdapter()); + new DataContractSerializerAdapter()*/); Console.WriteLine("Press enter to start"); Console.ReadLine(); diff --git a/ObjectSerialization.Performance/TestCases/TestCase.cs b/ObjectSerialization.Performance/TestCases/TestCase.cs index 7094d3e..4e12fc3 100644 --- a/ObjectSerialization.Performance/TestCases/TestCase.cs +++ b/ObjectSerialization.Performance/TestCases/TestCase.cs @@ -8,7 +8,7 @@ namespace ObjectSerialization.Performance.TestCases { abstract class TestCase { - private const int _measurementCount = 250000; + private const int _measurementCount = 200000; public abstract string Name { get; } public PerformanceResult Measure(ISerializerAdapter serializer) { diff --git a/ObjectSerialization.sln b/ObjectSerialization.sln index a52259e..0e59410 100644 --- a/ObjectSerialization.sln +++ b/ObjectSerialization.sln @@ -1,6 +1,6 @@  -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ObjectSerialization", "ObjectSerialization\ObjectSerialization.csproj", "{32D2BED8-AE96-4E80-A981-5188FEB260D4}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ObjectSerialization.UT", "ObjectSerialization.UT\ObjectSerialization.UT.csproj", "{25015080-9E1B-49F2-9F1F-D22C1418B25F}" @@ -13,6 +13,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ObjectSerialization.Performance", "ObjectSerialization.Performance\ObjectSerialization.Performance.csproj", "{724404A9-0638-4378-A0BC-D76B62FB0E3A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeBuilder", "..\CodeBuilder\CodeBuilder\CodeBuilder.csproj", "{22256B91-E772-40A0-BED3-AA6E10EEF1E5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeBuilder.UT", "..\CodeBuilder\CodeBuilder.UT\CodeBuilder.UT.csproj", "{900FC247-1330-4CBA-A1C7-A450993065C5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -53,6 +57,26 @@ Global {724404A9-0638-4378-A0BC-D76B62FB0E3A}.Release|Mixed Platforms.Build.0 = Release|x86 {724404A9-0638-4378-A0BC-D76B62FB0E3A}.Release|x86.ActiveCfg = Release|x86 {724404A9-0638-4378-A0BC-D76B62FB0E3A}.Release|x86.Build.0 = Release|x86 + {22256B91-E772-40A0-BED3-AA6E10EEF1E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {22256B91-E772-40A0-BED3-AA6E10EEF1E5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {22256B91-E772-40A0-BED3-AA6E10EEF1E5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {22256B91-E772-40A0-BED3-AA6E10EEF1E5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {22256B91-E772-40A0-BED3-AA6E10EEF1E5}.Debug|x86.ActiveCfg = Debug|Any CPU + {22256B91-E772-40A0-BED3-AA6E10EEF1E5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {22256B91-E772-40A0-BED3-AA6E10EEF1E5}.Release|Any CPU.Build.0 = Release|Any CPU + {22256B91-E772-40A0-BED3-AA6E10EEF1E5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {22256B91-E772-40A0-BED3-AA6E10EEF1E5}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {22256B91-E772-40A0-BED3-AA6E10EEF1E5}.Release|x86.ActiveCfg = Release|Any CPU + {900FC247-1330-4CBA-A1C7-A450993065C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {900FC247-1330-4CBA-A1C7-A450993065C5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {900FC247-1330-4CBA-A1C7-A450993065C5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {900FC247-1330-4CBA-A1C7-A450993065C5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {900FC247-1330-4CBA-A1C7-A450993065C5}.Debug|x86.ActiveCfg = Debug|Any CPU + {900FC247-1330-4CBA-A1C7-A450993065C5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {900FC247-1330-4CBA-A1C7-A450993065C5}.Release|Any CPU.Build.0 = Release|Any CPU + {900FC247-1330-4CBA-A1C7-A450993065C5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {900FC247-1330-4CBA-A1C7-A450993065C5}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {900FC247-1330-4CBA-A1C7-A450993065C5}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ObjectSerialization/Builders/BuildContext.cs b/ObjectSerialization/Builders/BuildContext.cs index 7be7196..36ea5fd 100644 --- a/ObjectSerialization/Builders/BuildContext.cs +++ b/ObjectSerialization/Builders/BuildContext.cs @@ -1,35 +1,34 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; +using System.Reflection.Emit; +using CodeBuilder; +using CodeBuilder.Expressions; using ObjectSerialization.Builders.Types; namespace ObjectSerialization.Builders { internal class BuildContext { - public readonly LabelTarget ReadReturnLabel = Expression.Label(typeof(object), "ret"); - public readonly ParameterExpression ReaderObject = Expression.Parameter(typeof(BinaryReader), "r"); + private readonly string _suffix; + public readonly Expression ReaderObject = Expr.Parameter(0, typeof(BinaryReader)); - public readonly ParameterExpression WriteObject = Expression.Variable(typeof(T), "v"); - public readonly ParameterExpression WriterObject = Expression.Parameter(typeof(BinaryWriter), "w"); + public readonly Expression WriteObject = Expr.Parameter(1, typeof(T)); + public readonly Expression WriterObject = Expr.Parameter(0, typeof(BinaryWriter)); private readonly List _readExpressions = new List(); private readonly List _writeExpressions = new List(); - private readonly ParameterExpression _writeParameter = Expression.Parameter(typeof(object), "o"); - public ParameterExpression ReadResultObject { get; private set; } + public LocalVariable ReadResultObject { get; private set; } - public BuildContext() + public BuildContext(string suffix) { - _writeExpressions.Add(Expression.Assign(WriteObject, Expression.Convert(_writeParameter, typeof(T)))); + _suffix = suffix; } - public BuildContext(ParameterExpression readResult) - : this() + public BuildContext(LocalVariable readResult, string suffix) + : this(suffix) { ReadResultObject = readResult; - _readExpressions.Add(Expression.Assign(ReadResultObject, BaseTypeSerializer.InstantiateNew(typeof(T)))); + _readExpressions.Add(Expr.DeclareLocal(ReadResultObject, BaseTypeSerializer.InstantiateNew(typeof(T)))); } public void AddReadExpression(Expression expr) @@ -42,42 +41,42 @@ public void AddWriteExpression(Expression expr) _writeExpressions.Add(expr); } - public Func GetDeserializeFn() + public Func GetDeserializeFn() { if (ReadResultObject != null) - _readExpressions.Add(ReturnValue(ReadResultObject)); + _readExpressions.Add(Expr.Return(Expr.ReadLocal(ReadResultObject))); - List expressions = _readExpressions.ToList(); + return DefineMethod>("Deserialize", typeof(T), new[] { typeof(BinaryReader) }, _readExpressions.ToArray()); - expressions.Add(Expression.Label(ReadReturnLabel, Expression.Convert(Expression.Default(typeof(T)), typeof(object)))); - Expression body = Expression.Block(ReadResultObject == null ? null : new[] { ReadResultObject }, expressions); - Expression> expression = Expression.Lambda>(body, ReaderObject); -#if DEBUG - DumpExpression("Deserialize", expression); -#endif - return expression.Compile(); } - public Action GetSerializeFn() + public Action GetSerializeFn() { - BlockExpression blockExpression = Expression.Block(new[] { WriteObject }, _writeExpressions); - Expression> expression = Expression.Lambda>(blockExpression, WriterObject, _writeParameter); -#if DEBUG - DumpExpression("Serialize", expression); -#endif - return expression.Compile(); + return DefineMethod>("Serialize", typeof(void), new[] { typeof(BinaryWriter), typeof(T) }, _writeExpressions.ToArray()); } public Expression ReturnValue(Expression result) { - return Expression.Return(ReadReturnLabel, Expression.Convert(result, typeof(object)), typeof(object)); + return Expr.Return(result); } - private void DumpExpression(string operation, Expression expression) + private void DumpExpression(DynamicMethod method, MethodBodyBuilder builder) { - object value = typeof(Expression).GetProperty("DebugView", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy) - .GetValue(expression, null); - Console.Write("{0} {1}: {2}\n", typeof(T).Name, operation, value); + Console.Write("{0} {1}:\n{2}\n\n", typeof(T).Name, method.Name, builder); + } + + private T DefineMethod(string name, Type returnType, Type[] parameters, params Expression[] body) + { + var method = new DynamicMethod(name + _suffix, returnType, parameters, true); + + var bodyBuilder = new MethodBodyBuilder(method, parameters); + bodyBuilder.AddStatements(body); +#if DEBUG + DumpExpression(method, bodyBuilder); +#endif + bodyBuilder.Compile(); + + return (T)(object)method.CreateDelegate(typeof(T)); } } } \ No newline at end of file diff --git a/ObjectSerialization/Builders/TypeMembersSerializerBuilder.cs b/ObjectSerialization/Builders/TypeMembersSerializerBuilder.cs index c281cb4..21b7b5c 100644 --- a/ObjectSerialization/Builders/TypeMembersSerializerBuilder.cs +++ b/ObjectSerialization/Builders/TypeMembersSerializerBuilder.cs @@ -1,106 +1,107 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; -using System.Runtime.Serialization; -using ObjectSerialization.Builders.Types; - -namespace ObjectSerialization.Builders -{ - internal class TypeMembersSerializerBuilder : SerializerBuilder - { - private static Func _deserializeFn; - private static Action _serializeFn; - - public static Func DeserializeFn - { - get - { - if (_deserializeFn == null) - Build(); - return _deserializeFn; - } - } - - public static Action SerializeFn - { - get - { - if (_serializeFn == null) - Build(); - return _serializeFn; - } - } - - public static IEnumerable GetFields(Type type) - { - if (type == null) - return Enumerable.Empty(); - - return type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly) - .Concat(GetFields(type.BaseType)); - } - - private static void Build() - { - try - { - var ctx = new BuildContext(Expression.Variable(typeof(T), "o")); - - IOrderedEnumerable fields = GetFields(typeof(T)) - .Where(ShouldBePersisted) - .OrderBy(f => f.Name); - - foreach (FieldInfo field in fields) - BuildFieldSerializer(field, ctx); - - _serializeFn = ctx.GetSerializeFn(); - _deserializeFn = ctx.GetDeserializeFn(); - } - catch (Exception e) - { - throw new SerializationException(e.Message, e); - } - } - - private static void BuildFieldSerializer(FieldInfo field, BuildContext ctx) - { - if (field.IsInitOnly) - throw new InvalidOperationException(string.Format("Unable to serialize readonly field {0} in type {1}. Please mark it with NonSerialized attribute or remove readonly modifier.", field.Name, typeof(T).FullName)); - - ISerializer serializer = Serializers.First(s => s.IsSupported(field.FieldType)); - ctx.AddWriteExpression(serializer.Write(ctx.WriterObject, GetFieldValue(ctx.WriteObject, field), field.FieldType)); - ctx.AddReadExpression(SetFieldValue(ctx.ReadResultObject, field, serializer.Read(ctx.ReaderObject, field.FieldType))); - } - - private static Expression GetFieldValue(Expression instance, FieldInfo field) - { - return Expression.Field(instance, field); - } - - private static PropertyInfo GetPropertyForBackingField(FieldInfo field) - { - string propertyName = field.Name.Substring(1, field.Name.IndexOf('>') - 1); - PropertyInfo propertyForBackingField = field.DeclaringType.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); - return propertyForBackingField; - } - - private static Expression SetFieldValue(Expression instance, FieldInfo field, Expression valueExpression) - { - return Expression.Assign(Expression.Field(instance, field), valueExpression); - } - - private static bool ShouldBePersisted(FieldInfo field) - { - if (field.GetCustomAttributes(typeof(NonSerializedAttribute), true).Length > 0) - return false; - - if (field.Name.EndsWith("k__BackingField") && GetPropertyForBackingField(field).GetCustomAttributes(typeof(NonSerializedBackendAttribute), true).Length > 0) - return false; - - return true; - } - } +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.Serialization; +using CodeBuilder; +using CodeBuilder.Expressions; +using ObjectSerialization.Builders.Types; + +namespace ObjectSerialization.Builders +{ + internal class TypeMembersSerializerBuilder : SerializerBuilder + { + private static Func _deserializeFn; + private static Action _serializeFn; + + public static Func DeserializeFn + { + get + { + if (_deserializeFn == null) + Build(); + return _deserializeFn; + } + } + + public static Action SerializeFn + { + get + { + if (_serializeFn == null) + Build(); + return _serializeFn; + } + } + + public static IEnumerable GetFields(Type type) + { + if (type == null) + return Enumerable.Empty(); + + return type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .Concat(GetFields(type.BaseType)); + } + + private static void Build() + { + try + { + var ctx = new BuildContext(Expr.LocalVariable(typeof(T), "o"), "Members"); + + IOrderedEnumerable fields = GetFields(typeof(T)) + .Where(ShouldBePersisted) + .OrderBy(f => f.Name); + + foreach (FieldInfo field in fields) + BuildFieldSerializer(field, ctx); + + _serializeFn = ctx.GetSerializeFn(); + _deserializeFn = ctx.GetDeserializeFn(); + } + catch (Exception e) + { + throw new SerializationException(e.Message, e); + } + } + + private static void BuildFieldSerializer(FieldInfo field, BuildContext ctx) + { + if (field.IsInitOnly) + throw new InvalidOperationException(string.Format("Unable to serialize readonly field {0} in type {1}. Please mark it with NonSerialized attribute or remove readonly modifier.", field.Name, typeof(T).FullName)); + + ISerializer serializer = Serializers.First(s => s.IsSupported(field.FieldType)); + ctx.AddWriteExpression(serializer.Write(ctx.WriterObject, GetFieldValue(ctx.WriteObject, field), field.FieldType)); + ctx.AddReadExpression(SetFieldValue(Expr.ReadLocal(ctx.ReadResultObject), field, serializer.Read(ctx.ReaderObject, field.FieldType))); + } + + private static Expression GetFieldValue(Expression instance, FieldInfo field) + { + return Expr.ReadField(instance, field); + } + + private static PropertyInfo GetPropertyForBackingField(FieldInfo field) + { + string propertyName = field.Name.Substring(1, field.Name.IndexOf('>') - 1); + PropertyInfo propertyForBackingField = field.DeclaringType.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); + return propertyForBackingField; + } + + private static Expression SetFieldValue(Expression instance, FieldInfo field, Expression valueExpression) + { + return Expr.WriteField(instance, field, valueExpression); + } + + private static bool ShouldBePersisted(FieldInfo field) + { + if (field.GetCustomAttributes(typeof(NonSerializedAttribute), true).Length > 0) + return false; + + if (field.Name.EndsWith("k__BackingField") && GetPropertyForBackingField(field).GetCustomAttributes(typeof(NonSerializedBackendAttribute), true).Length > 0) + return false; + + return true; + } + } } \ No newline at end of file diff --git a/ObjectSerialization/Builders/TypeSerializerBuilder.cs b/ObjectSerialization/Builders/TypeSerializerBuilder.cs index 346479b..ddc73f7 100644 --- a/ObjectSerialization/Builders/TypeSerializerBuilder.cs +++ b/ObjectSerialization/Builders/TypeSerializerBuilder.cs @@ -7,10 +7,10 @@ namespace ObjectSerialization.Builders { internal class TypeSerializerBuilder : SerializerBuilder { - private static Func _deserializeFn; - private static Action _serializeFn; + private static Func _deserializeFn; + private static Action _serializeFn; - public static Func DeserializeFn + public static Func DeserializeFn { get { @@ -20,7 +20,7 @@ public static Func DeserializeFn } } - public static Action SerializeFn + public static Action SerializeFn { get { @@ -30,9 +30,19 @@ public static Action SerializeFn } } + public static void SerializeWithCast(BinaryWriter writer, object value) + { + SerializeFn(writer, (T)value); + } + + public static object DeserializeWithCast(BinaryReader reader) + { + return DeserializeFn(reader); + } + private static void Build() { - var ctx = new BuildContext(); + var ctx = new BuildContext(""); BuildTypeSerializer(typeof(T), ctx); _serializeFn = ctx.GetSerializeFn(); _deserializeFn = ctx.GetDeserializeFn(); diff --git a/ObjectSerialization/Builders/Types/ArrayTypeSerializer.cs b/ObjectSerialization/Builders/Types/ArrayTypeSerializer.cs index e61d077..f62a9b9 100644 --- a/ObjectSerialization/Builders/Types/ArrayTypeSerializer.cs +++ b/ObjectSerialization/Builders/Types/ArrayTypeSerializer.cs @@ -1,6 +1,6 @@ using System; -using System.IO; -using System.Linq.Expressions; +using CodeBuilder; +using CodeBuilder.Expressions; using ObjectSerialization.Factories; namespace ObjectSerialization.Builders.Types @@ -16,25 +16,25 @@ public bool IsSupported(Type type) public Expression Write(Expression writerObject, Expression value, Type valueType) { - /*BinaryWriter w; + /*BinaryWriter w; T[] v; if (v != null) { - w.Write(v.Length); - int c = v.Length; - int s = TypeSerializerFactory.GetSerializer(typeof(T)); - for (var i = 0; i < c; ++i) - s.Invoke(w, v[i]); + w.Write(v.Length); + int c = v.Length; + int s = TypeSerializerFactory.GetSerializer(); + for (var i = 0; i < c; ++i) + s.Invoke(w, v[i]); } else - w.Write(-1);*/ + w.Write(-1);*/ - Expression checkNotNull = CheckNotNull(value, valueType); + var checkNotNull = CheckNotNull(value, valueType); - BlockExpression forLoop = CreateWriteLoop(writerObject, value, valueType); - BlockExpression arrayWrite = Expression.Block(GetWriteExpression(Expression.Property(value, "Length"), writerObject), forLoop); + var forLoop = CreateWriteLoop(writerObject, value, valueType); + var arrayWrite = Expr.Block(GetWriteExpression(Expr.ArrayLength(value), writerObject), forLoop); - return Expression.IfThenElse(checkNotNull, arrayWrite, GetWriteExpression(Expression.Constant(-1), writerObject)); + return Expr.IfThenElse(checkNotNull, arrayWrite, GetWriteExpression(Expr.Constant(-1), writerObject)); } public Expression Read(Expression readerObject, Type expectedValueType) @@ -45,70 +45,68 @@ public Expression Read(Expression readerObject, Type expectedValueType) return null; T[]v=new T[c]; - int s = TypeSerializerFactory.GetDeserializer(typeof (T)); + int s = TypeSerializerFactory.GetDeserializer(); for(var i=0 ; i < c; ++i) v[i] = s.Invoke(r); return v; */ - ParameterExpression count = Expression.Variable(typeof(int), "c"); - BinaryExpression countRead = Expression.Assign(count, GetReadExpression("ReadInt32", readerObject)); + var count = Expr.LocalVariable(typeof(int), "c"); + var countRead = Expr.DeclareLocal(count, GetReadExpression("ReadInt32", readerObject)); - BlockExpression expression = Expression.Block(new[] { count }, + var expression = Expr.ValueBlock( + expectedValueType, countRead, - Expression.Condition( - Expression.Equal(count, Expression.Constant(-1)), - Expression.Constant(null, expectedValueType), + Expr.IfThenElse( + Expr.Equal(Expr.ReadLocal(count), Expr.Constant(-1)), + Expr.Null(expectedValueType), CreateReadLoop(readerObject, expectedValueType, count))); return expression; } #endregion - private static BlockExpression CreateWriteLoop(Expression writerObject, Expression value, Type valueType) + private static Expression CreateWriteLoop(Expression writerObject, Expression value, Type valueType) { - ParameterExpression index = Expression.Parameter(typeof(int), "i"); - ParameterExpression count = Expression.Parameter(typeof(int), "c"); - ParameterExpression serializer = Expression.Parameter(typeof(Action), "s"); - LabelTarget loopEndLabel = Expression.Label(); - - return Expression.Block( - new[] { index, count, serializer }, - Expression.Assign(index, Expression.Constant(0, typeof(int))), - Expression.Assign(count, Expression.Property(value, "Length")), - Expression.Assign(serializer, GetSerializer(Expression.Constant(valueType.GetElementType()))), - Expression.Loop( - Expression.IfThenElse( - Expression.LessThan(index, count), - Expression.Block( - CallSerializeWithConvert(serializer, Expression.ArrayAccess(value, index), writerObject), - Expression.PreIncrementAssign(index)), - Expression.Break(loopEndLabel)), - loopEndLabel)); + var index = Expr.LocalVariable(typeof(int), "i"); + var count = Expr.LocalVariable(typeof(int), "c"); + var serializer = Expr.LocalVariable(GetWriteSerializerDelegateType(valueType.GetElementType()), "s"); + + return Expr.Block( + Expr.DeclareLocal(index, Expr.Constant(0)), + Expr.DeclareLocal(count, Expr.ArrayLength(value)), + Expr.DeclareLocal(serializer, GetSerializer(valueType.GetElementType())), + Expr.Loop( + Expr.IfThenElse( + Expr.Less(Expr.ReadLocal(index), Expr.ReadLocal(count)), + Expr.Block( + CallSerialize(Expr.ReadLocal(serializer), Expr.ReadArray(value, Expr.ReadLocal(index)), writerObject), + Expr.WriteLocal(index, Expr.Add(Expr.ReadLocal(index), Expr.Constant(1)))), + Expr.LoopBreak()))); } - private Expression CreateReadLoop(Expression readerObject, Type expectedValueType, ParameterExpression count) + private Expression CreateReadLoop(Expression readerObject, Type expectedValueType, LocalVariable count) { - ParameterExpression index = Expression.Parameter(typeof(int), "i"); - ParameterExpression deserializer = Expression.Parameter(typeof(Func), "s"); - ParameterExpression result = Expression.Parameter(expectedValueType, "r"); - LabelTarget loopEndLabel = Expression.Label(expectedValueType); - - BlockExpression forLoop = Expression.Block( - new[] { index, result, deserializer }, - Expression.Assign(result, Expression.NewArrayBounds(expectedValueType.GetElementType(), count)), - Expression.Assign(index, Expression.Constant(0, typeof(int))), - Expression.Assign(deserializer, GetDeserializer(Expression.Constant(expectedValueType.GetElementType()))), - Expression.Loop( - Expression.IfThenElse( - Expression.LessThan(index, count), - Expression.Block( - Expression.Assign(Expression.ArrayAccess(result, index), CallDeserialize(deserializer, expectedValueType.GetElementType(), readerObject)), - Expression.PreIncrementAssign(index)), - Expression.Break(loopEndLabel, result)), - loopEndLabel)); + var index = Expr.LocalVariable(typeof(int), "i"); + var deserializer = Expr.LocalVariable(GetReadSerializerDelegateType(expectedValueType.GetElementType()), "s"); + var result = Expr.LocalVariable(expectedValueType, "r"); + + var forLoop = Expr.ValueBlock( + expectedValueType, + Expr.DeclareLocal(result, Expr.NewArray(expectedValueType.GetElementType(), Expr.ReadLocal(count))), + Expr.DeclareLocal(index, Expr.Constant(0)), + Expr.DeclareLocal(deserializer, GetDeserializer(expectedValueType.GetElementType())), + Expr.Loop( + Expr.IfThenElse( + Expr.Less(Expr.ReadLocal(index), Expr.ReadLocal(count)), + Expr.Block( + Expr.WriteArray(Expr.ReadLocal(result), Expr.ReadLocal(index), CallDeserialize(Expr.ReadLocal(deserializer), readerObject)), + Expr.WriteLocal(index, Expr.Add(Expr.ReadLocal(index), Expr.Constant(1)))), + Expr.LoopBreak())), + Expr.ReadLocal(result)); return forLoop; } + } } \ No newline at end of file diff --git a/ObjectSerialization/Builders/Types/BaseTypeSerializer.cs b/ObjectSerialization/Builders/Types/BaseTypeSerializer.cs index c5d84c9..d083cd2 100644 --- a/ObjectSerialization/Builders/Types/BaseTypeSerializer.cs +++ b/ObjectSerialization/Builders/Types/BaseTypeSerializer.cs @@ -1,6 +1,8 @@ using System; -using System.Linq.Expressions; +using System.IO; using System.Runtime.Serialization; +using CodeBuilder; +using CodeBuilder.Expressions; namespace ObjectSerialization.Builders.Types { @@ -9,53 +11,70 @@ internal class BaseTypeSerializer public static Expression InstantiateNew(Type type) { if (type.IsClass && type.GetConstructor(new Type[0]) == null) - return Expression.TypeAs(Expression.Call(typeof(FormatterServices), "GetUninitializedObject", null, Expression.Constant(type)), type); - return Expression.New(type); + return Expr.Convert(Expr.Call(typeof(FormatterServices), "GetUninitializedObject", Expr.Constant(type)), type); + return Expr.New(type); } - protected static Expression CallDeserialize(Expression deserializer, Type propertyType, Expression readerObject) + protected static Expression CallDeserialize(Expression deserializer, Expression readerObject) { - return Expression.Convert(Expression.Call(deserializer, "Invoke", null, readerObject), propertyType); + return Expr.Call(deserializer, "Invoke", readerObject); + } + + protected static Expression CallDeserializeWithConvert(Expression deserializer, Type propertyType, Expression readerObject) + { + return Expr.Convert(Expr.Call(deserializer, "Invoke", readerObject), propertyType); } protected static Expression CallSerialize(Expression serializer, Expression value, Expression writerObject) { - return Expression.Call(serializer, "Invoke", null, writerObject, value); + return Expr.Call(serializer, "Invoke", writerObject, value); } - protected static Expression CallSerializeWithConvert(Expression serializer, Expression value, Expression writerObject) + protected static Expression CallSerializeWithConvert(Expression serializer, Expression value, Type valueType, Expression writerObject) { - return Expression.Call(serializer, "Invoke", null, writerObject, Expression.Convert(value, typeof(object))); + return Expr.Call(serializer, "Invoke", writerObject, Expr.Convert(value, valueType)); } protected static Expression CheckNotNull(Expression value, Type valueType) { - return Expression.ReferenceNotEqual(value, Expression.Constant(null, valueType)); + //return Expr.ReferenceNotEqual(value, Expression.Constant(null, valueType)); + if (!valueType.IsClass && !valueType.IsInterface) throw new ArgumentException("Expected class type, got: " + valueType); + return Expr.IfThenElse(value, Expr.Constant(true), Expr.Constant(false)); } protected static Expression GetActualValueType(Expression value) { - return Expression.Call(Expression.TypeAs(value, typeof(object)), "GetType", null); + return Expr.Call(Expr.Convert(value, typeof(object)), "GetType"); //TODO: optimize? } protected static Expression GetDeserializer(Expression type) { - return Expression.Call(typeof(TSerializerFactory), "GetDeserializer", null, type); + return Expr.Call(typeof(TSerializerFactory), "GetDeserializer", type); + } + + protected static Expression GetDeserializer(Type type) + { + return Expr.Call(typeof(TSerializerFactory), "GetDeserializer", new[] { type }); } protected static Expression GetReadExpression(string method, Expression reader) { - return Expression.Call(reader, method, new Type[0]); + return Expr.Call(reader, method); } protected static Expression GetSerializer(Expression type) { - return Expression.Call(typeof(TSerializerFactory), "GetSerializer", null, type); + return Expr.Call(typeof(TSerializerFactory), "GetSerializer", type); + } + + protected static Expression GetSerializer(Type type) + { + return Expr.Call(typeof(TSerializerFactory), "GetSerializer", new[] { type }); } protected static Expression GetWriteExpression(Expression valueExpression, Expression writer) { - return Expression.Call(writer, "Write", null, valueExpression); + return Expr.Call(writer, "Write", valueExpression); } protected static Expression ReloadType(Expression readerObject) @@ -66,18 +85,28 @@ protected static Expression ReloadType(Expression readerObject) protected static Expression WriteObjectType(Expression value, Expression objectWriter) { Expression valueType = GetActualValueType(value); - MemberExpression typeFullName = Expression.Property(valueType, "FullName"); + var typeFullName = Expr.ReadProperty(valueType, typeof(Type).GetProperty("FullName")); return GetWriteExpression(typeFullName, objectWriter); } protected Expression GetDirectDeserializer(Type builderType, Type valueType) { - return Expression.Property(null, builderType.MakeGenericType(valueType), "DeserializeFn"); + return Expr.ReadProperty(builderType.MakeGenericType(valueType).GetProperty("DeserializeFn")); } protected Expression GetDirectSerializer(Type builderType, Type valueType) { - return Expression.Property(null, builderType.MakeGenericType(valueType), "SerializeFn"); + return Expr.ReadProperty(builderType.MakeGenericType(valueType).GetProperty("SerializeFn")); + } + + protected static Type GetWriteSerializerDelegateType(Type type) + { + return typeof(Action<,>).MakeGenericType(typeof(BinaryWriter), type); + } + + protected static Type GetReadSerializerDelegateType(Type type) + { + return typeof(Func<,>).MakeGenericType(typeof(BinaryReader), type); } } } \ No newline at end of file diff --git a/ObjectSerialization/Builders/Types/ClassTypeSerializer.cs b/ObjectSerialization/Builders/Types/ClassTypeSerializer.cs index a04a4ef..9caee3c 100644 --- a/ObjectSerialization/Builders/Types/ClassTypeSerializer.cs +++ b/ObjectSerialization/Builders/Types/ClassTypeSerializer.cs @@ -1,5 +1,6 @@ using System; -using System.Linq.Expressions; +using CodeBuilder; +using CodeBuilder.Expressions; using ObjectSerialization.Types; namespace ObjectSerialization.Builders.Types @@ -35,19 +36,19 @@ public Expression Write(Expression writerObject, Expression value, Type valueTyp Expression checkNotNull = CheckNotNull(value, valueType); - BlockExpression serializeClass = Expression.Block( - GetWriteExpression(Expression.Constant((byte)1), writerObject), + BlockExpression serializeClass = Expr.Block( + GetWriteExpression(Expr.Constant((byte)1), writerObject), CallSerialize(GetDirectSerializer(typeof(TypeMembersSerializerBuilder<>), valueType), value, writerObject)); - BlockExpression serializePolymorphicClass = Expression.Block( - GetWriteExpression(Expression.Constant((byte)2), writerObject), + BlockExpression serializePolymorphicClass = Expr.Block( + GetWriteExpression(Expr.Constant((byte)2), writerObject), CallSerialize(GetSerializerField(WriteTypeInfo(writerObject, value)), value, writerObject)); Expression serializationExpression = GetSerializationExpression(value, valueType, serializeClass, serializePolymorphicClass); - return Expression.IfThenElse(checkNotNull, + return Expr.IfThenElse(checkNotNull, serializationExpression, - GetWriteExpression(Expression.Constant((byte)0), writerObject)); + GetWriteExpression(Expr.Constant((byte)0), writerObject)); } @@ -61,30 +62,30 @@ public Expression Read(Expression readerObject, Type expectedValueType) ? TypeMembersSerializerBuilder.DeserializeFn.Invoke(r) :TypeInfoWriter.ReadInfo(r).Deserializer.Invoke(r));*/ - ParameterExpression flag = Expression.Variable(typeof(byte), "b"); - BinaryExpression readFlag = Expression.Assign(flag, GetReadExpression("ReadByte", readerObject)); - Expression deserializeClass = CallDeserialize(GetDirectDeserializer(typeof(TypeMembersSerializerBuilder<>), expectedValueType), expectedValueType, readerObject); - Expression deserializePolymorphic = CallDeserialize(GetDeserializerField(ReadTypeInfo(readerObject)), expectedValueType, readerObject); + var flag = Expr.LocalVariable(typeof(byte), "b"); + var readFlag = Expr.DeclareLocal(flag, GetReadExpression("ReadByte", readerObject)); + Expression deserializeClass = CallDeserialize(GetDirectDeserializer(typeof(TypeMembersSerializerBuilder<>), expectedValueType), readerObject); + Expression deserializePolymorphic = CallDeserializeWithConvert(GetDeserializerField(ReadTypeInfo(readerObject)), expectedValueType, readerObject); - ConditionalExpression deserialization = Expression.Condition( - Expression.Equal(flag, Expression.Constant((byte)0)), - Expression.Constant(null, expectedValueType), - GetDeserializationExpression(flag,expectedValueType, deserializeClass, deserializePolymorphic)); + var deserialization = Expr.IfThenElse( + Expr.ReadLocal(flag), + GetDeserializationExpression(Expr.ReadLocal(flag), expectedValueType, deserializeClass, deserializePolymorphic), + Expr.Null(expectedValueType)); - return Expression.Block(new[] { flag }, readFlag, deserialization); + return Expr.ValueBlock(expectedValueType, readFlag, deserialization); } #endregion - private static Expression GetDeserializationExpression(ParameterExpression flag, Type expectedValueType, Expression deserializeClass, Expression deserializePolymorphic) + private static Expression GetDeserializationExpression(Expression flag, Type expectedValueType, Expression deserializeClass, Expression deserializePolymorphic) { if (expectedValueType.IsSealed) return deserializeClass; if (IsPurePolymorphic(expectedValueType)) return deserializePolymorphic; - return Expression.Condition( - Expression.Equal(flag, Expression.Constant((byte)1)), + return Expr.IfThenElse( + Expr.Equal(flag, Expr.Constant((byte)1)), deserializeClass, deserializePolymorphic); } @@ -97,8 +98,8 @@ private static Expression GetSerializationExpression(Expression value, Type valu if (IsPurePolymorphic(valueType)) return serializePolymorphicClass; - return Expression.IfThenElse( - Expression.Equal(GetActualValueType(value), Expression.Constant(valueType)), + return Expr.IfThenElse( + Expr.Equal(GetActualValueType(value), Expr.Constant(valueType)), serializeClass, serializePolymorphicClass ); @@ -111,22 +112,22 @@ private static bool IsPurePolymorphic(Type valueType) private Expression GetDeserializerField(Expression typeInfo) { - return Expression.Field(typeInfo, "Deserializer"); + return Expr.ReadField(typeInfo, "Deserializer"); } private Expression GetSerializerField(Expression typeInfo) { - return Expression.Field(typeInfo, "Serializer"); + return Expr.ReadField(typeInfo, "Serializer"); } - private MethodCallExpression ReadTypeInfo(Expression readerObject) + private CallExpression ReadTypeInfo(Expression readerObject) { - return Expression.Call(typeof(TypeInfoWriter), "ReadInfo", null, readerObject); + return Expr.Call(typeof(TypeInfoWriter), "ReadInfo", readerObject); } private Expression WriteTypeInfo(Expression writerObject, Expression value) { - return Expression.Call(typeof(TypeInfoWriter), "WriteInfo", null, writerObject, GetActualValueType(value)); + return Expr.Call(typeof(TypeInfoWriter), "WriteInfo", writerObject, GetActualValueType(value)); } } } \ No newline at end of file diff --git a/ObjectSerialization/Builders/Types/CollectionTypeSerializer.cs b/ObjectSerialization/Builders/Types/CollectionTypeSerializer.cs index 3939b64..264cf4f 100644 --- a/ObjectSerialization/Builders/Types/CollectionTypeSerializer.cs +++ b/ObjectSerialization/Builders/Types/CollectionTypeSerializer.cs @@ -1,9 +1,9 @@ using System; using System.Collections; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Linq.Expressions; +using CodeBuilder; +using CodeBuilder.Expressions; using ObjectSerialization.Factories; namespace ObjectSerialization.Builders.Types @@ -24,7 +24,7 @@ public Expression Write(Expression writerObject, Expression value, Type valueTyp if (v!= null) { w.Write(v.Count); - int s = TypeSerializerFactory.GetSerializer(typeof(T)); + int s = TypeSerializerFactory.GetSerializer(); IEnumerator e = v.GetEnumerator(); try @@ -44,11 +44,11 @@ public Expression Write(Expression writerObject, Expression value, Type valueTyp Expression checkNotNull = CheckNotNull(value, valueType); - BlockExpression collectionWrite = Expression.Block( - GetWriteExpression(Expression.Property(value, "Count"), writerObject), + BlockExpression collectionWrite = Expr.Block( + GetWriteExpression(Expr.ReadProperty(value, "Count"), writerObject), CreateWriteLoop(writerObject, value, valueType)); - return Expression.IfThenElse(checkNotNull, collectionWrite, GetWriteExpression(Expression.Constant(-1), writerObject)); + return Expr.IfThenElse(checkNotNull, collectionWrite, GetWriteExpression(Expr.Constant(-1), writerObject)); } public Expression Read(Expression readerObject, Type expectedValueType) @@ -59,20 +59,21 @@ public Expression Read(Expression readerObject, Type expectedValueType) return null; TCollection v=new TCollection(); - int s = TypeSerializerFactory.GetDeserializer(typeof(T)); + int s = TypeSerializerFactory.GetDeserializer(); for(var i=0 ; i < c; ++i) v.Add(s.Invoke(r)); return v;*/ - ParameterExpression count = Expression.Variable(typeof(int), "c"); - BinaryExpression countRead = Expression.Assign(count, GetReadExpression("ReadInt32", readerObject)); + var count = Expr.LocalVariable(typeof(int), "c"); + var countRead = Expr.DeclareLocal(count, GetReadExpression("ReadInt32", readerObject)); - BlockExpression expression = Expression.Block(new[] { count }, + var expression = Expr.ValueBlock( + expectedValueType, countRead, - Expression.Condition( - Expression.Equal(count, Expression.Constant(-1)), - Expression.Constant(null, expectedValueType), - CreateReadLoop(readerObject, expectedValueType, count))); + Expr.IfThenElse( + Expr.Equal(Expr.ReadLocal(count), Expr.Constant(-1)), + Expr.Null(expectedValueType), + CreateReadLoop(readerObject, expectedValueType, Expr.ReadLocal(count)))); return expression; } @@ -89,26 +90,25 @@ private static Type GetCollectionType(Type type) return type.GetInterfaces().FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollection<>)); } - private Expression CreateReadLoop(Expression readerObject, Type expectedValueType, ParameterExpression count) + private Expression CreateReadLoop(Expression readerObject, Type expectedValueType, Expression count) { - ParameterExpression index = Expression.Parameter(typeof(int), "i"); - ParameterExpression deserializer = Expression.Parameter(typeof(Func), "s"); - ParameterExpression result = Expression.Parameter(expectedValueType, "v"); - LabelTarget loopEndLabel = Expression.Label(expectedValueType); - - BlockExpression forLoop = Expression.Block( - new[] { index, result, deserializer }, - Expression.Assign(result, InstantiateNew(expectedValueType)), - Expression.Assign(index, Expression.Constant(0, typeof(int))), - Expression.Assign(deserializer, GetDeserializer(Expression.Constant(GetCollectionItemType(expectedValueType)))), - Expression.Loop( - Expression.IfThenElse( - Expression.LessThan(index, count), - Expression.Block( - Expression.Call(Expression.TypeAs(result, GetCollectionType(expectedValueType)), "Add", null, CallDeserialize(deserializer, GetCollectionItemType(expectedValueType), readerObject)), - Expression.PreIncrementAssign(index)), - Expression.Break(loopEndLabel, result)), - loopEndLabel)); + var index = Expr.LocalVariable(typeof(int), "i"); + var deserializer = Expr.LocalVariable(GetReadSerializerDelegateType(GetCollectionItemType(expectedValueType)), "s"); + var result = Expr.LocalVariable(expectedValueType, "v"); + + var forLoop = Expr.ValueBlock( + expectedValueType, + Expr.DeclareLocal(result, InstantiateNew(expectedValueType)), + Expr.DeclareLocal(index, Expr.Constant(0)), + Expr.DeclareLocal(deserializer, GetDeserializer(GetCollectionItemType(expectedValueType))), + Expr.Loop( + Expr.IfThenElse( + Expr.Less(Expr.ReadLocal(index), count), + Expr.Block( + Expr.Call(Expr.Convert(Expr.ReadLocal(result), GetCollectionType(expectedValueType)), "Add", CallDeserialize(Expr.ReadLocal(deserializer), readerObject)), + Expr.WriteLocal(index,Expr.Add(Expr.ReadLocal(index),Expr.Constant(1)))), + Expr.LoopBreak())), + Expr.ReadLocal(result)); return forLoop; } @@ -116,22 +116,19 @@ private Expression CreateReadLoop(Expression readerObject, Type expectedValueTyp private Expression CreateWriteLoop(Expression writerObject, Expression value, Type valueType) { Type enumeratorType = GetEnumeratorType(valueType); - ParameterExpression enumerator = Expression.Parameter(enumeratorType, "e"); - ParameterExpression serializer = Expression.Parameter(typeof(Action), "s"); - LabelTarget loopEndLabel = Expression.Label(); - - return Expression.Block( - new[] { enumerator, serializer }, - Expression.Assign(serializer, GetSerializer(Expression.Constant(GetCollectionItemType(valueType)))), - Expression.Assign(enumerator, Expression.Convert(Expression.Call(value, "GetEnumerator", null), enumeratorType)), - Expression.TryFinally( - Expression.Loop( - Expression.IfThenElse( - Expression.Call(Expression.TypeAs(enumerator, typeof(IEnumerator)), "MoveNext", null), - CallSerializeWithConvert(serializer, Expression.Property(enumerator, "Current"), writerObject), - Expression.Break(loopEndLabel)), - loopEndLabel), - Expression.Call(Expression.TypeAs(enumerator, typeof(IDisposable)), "Dispose", null))); + var enumerator = Expr.LocalVariable(enumeratorType, "e"); + var serializer = Expr.LocalVariable(GetWriteSerializerDelegateType(GetCollectionItemType(valueType)), "s"); + + return Expr.Block( + Expr.DeclareLocal(serializer, GetSerializer(GetCollectionItemType(valueType))), + Expr.DeclareLocal(enumerator, Expr.Convert(Expr.Call(value, "GetEnumerator"), enumeratorType)), + Expr.TryFinally( + Expr.Loop( + Expr.IfThenElse( + Expr.Call(Expr.Convert(Expr.ReadLocal(enumerator), typeof(IEnumerator)), "MoveNext"), + CallSerialize(Expr.ReadLocal(serializer), Expr.ReadProperty(Expr.ReadLocal(enumerator), "Current"), writerObject), + Expr.LoopBreak())), + Expr.Call(Expr.Convert(Expr.ReadLocal(enumerator), typeof(IDisposable)), "Dispose"))); } private Type GetEnumeratorType(Type collectionType) diff --git a/ObjectSerialization/Builders/Types/ISerializer.cs b/ObjectSerialization/Builders/Types/ISerializer.cs index fc2a355..a550acf 100644 --- a/ObjectSerialization/Builders/Types/ISerializer.cs +++ b/ObjectSerialization/Builders/Types/ISerializer.cs @@ -1,5 +1,5 @@ using System; -using System.Linq.Expressions; +using CodeBuilder.Expressions; namespace ObjectSerialization.Builders.Types { diff --git a/ObjectSerialization/Builders/Types/PredefinedTypeSerializer.cs b/ObjectSerialization/Builders/Types/PredefinedTypeSerializer.cs index 25caad7..da8044f 100644 --- a/ObjectSerialization/Builders/Types/PredefinedTypeSerializer.cs +++ b/ObjectSerialization/Builders/Types/PredefinedTypeSerializer.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Linq.Expressions; +using CodeBuilder.Expressions; namespace ObjectSerialization.Builders.Types { diff --git a/ObjectSerialization/Builders/Types/StringTypeSerializer.cs b/ObjectSerialization/Builders/Types/StringTypeSerializer.cs index c87a4a1..78bb535 100644 --- a/ObjectSerialization/Builders/Types/StringTypeSerializer.cs +++ b/ObjectSerialization/Builders/Types/StringTypeSerializer.cs @@ -1,7 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Linq.Expressions; +using CodeBuilder; +using CodeBuilder.Expressions; namespace ObjectSerialization.Builders.Types { @@ -26,9 +27,9 @@ public Expression Write(Expression writerObject, Expression value, Type valueTyp Expression notNull = CheckNotNull(value, valueType); - return Expression.Block( + return Expr.Block( GetWriteExpression(notNull, writerObject), - Expression.IfThen( + Expr.IfThen( notNull, GetWriteExpression(value, writerObject))); } @@ -39,10 +40,10 @@ public Expression Read(Expression readerObject, Type expectedValueType) BinaryReader r; return r.ReadBoolean()?r.ReadString():null;*/ - return Expression.Condition( + return Expr.IfThenElse( GetReadExpression("ReadBoolean", readerObject), GetReadExpression("Read" + expectedValueType.Name, readerObject), - Expression.Constant(null, expectedValueType)); + Expr.Null(expectedValueType)); } #endregion diff --git a/ObjectSerialization/Builders/Types/ValueTypeSerializer.cs b/ObjectSerialization/Builders/Types/ValueTypeSerializer.cs index 93d49ea..62237d6 100644 --- a/ObjectSerialization/Builders/Types/ValueTypeSerializer.cs +++ b/ObjectSerialization/Builders/Types/ValueTypeSerializer.cs @@ -1,5 +1,5 @@ using System; -using System.Linq.Expressions; +using CodeBuilder.Expressions; namespace ObjectSerialization.Builders.Types { @@ -19,7 +19,7 @@ public Expression Write(Expression writerObject, Expression value, Type valueTyp TypeMembersSerializerBuilder.SerializeFn.Invoke(w, v); */ - return CallSerializeWithConvert(GetDirectSerializer(typeof(TypeMembersSerializerBuilder<>),valueType), value, writerObject); + return CallSerialize(GetDirectSerializer(typeof(TypeMembersSerializerBuilder<>),valueType), value, writerObject); } public Expression Read(Expression readerObject, Type expectedValueType) @@ -27,7 +27,7 @@ public Expression Read(Expression readerObject, Type expectedValueType) /*BinaryReader r; return TypeMembersSerializerBuilder.DeserializeFn.Invoke(r) */ - return CallDeserialize(GetDirectDeserializer(typeof(TypeMembersSerializerBuilder<>), expectedValueType), expectedValueType, readerObject); + return CallDeserialize(GetDirectDeserializer(typeof(TypeMembersSerializerBuilder<>), expectedValueType), readerObject); } #endregion diff --git a/ObjectSerialization/Factories/TypeSerializerFactory.cs b/ObjectSerialization/Factories/TypeSerializerFactory.cs index 079dce3..598ec8c 100644 --- a/ObjectSerialization/Factories/TypeSerializerFactory.cs +++ b/ObjectSerialization/Factories/TypeSerializerFactory.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using ObjectSerialization.Builders; using ObjectSerialization.Types; namespace ObjectSerialization.Factories @@ -8,12 +9,17 @@ internal class TypeSerializerFactory { public static Func GetDeserializer(string typeFullName) { - return TypeInfoRepository.GetTypeInfo(typeFullName).Deserializer; + return TypeInfoRepository.GetTypeInfo(typeFullName).Deserializer; } public static Func GetDeserializer(Type type) { - return TypeInfoRepository.GetTypeInfo(type).Deserializer; + return TypeInfoRepository.GetTypeInfo(type).Deserializer; + } + + public static Func GetDeserializer() + { + return TypeSerializerBuilder.DeserializeFn; } public static Action GetSerializer(string typeFullName) @@ -25,5 +31,10 @@ public static Action GetSerializer(Type type) { return TypeInfoRepository.GetTypeInfo(type).Serializer; } + + public static Action GetSerializer() + { + return TypeSerializerBuilder.SerializeFn; + } } } \ No newline at end of file diff --git a/ObjectSerialization/ObjectSerialization.csproj b/ObjectSerialization/ObjectSerialization.csproj index 8d00879..53b626b 100644 --- a/ObjectSerialization/ObjectSerialization.csproj +++ b/ObjectSerialization/ObjectSerialization.csproj @@ -55,6 +55,12 @@ + + + {22256B91-E772-40A0-BED3-AA6E10EEF1E5} + CodeBuilder + +