public override ValueSerializer BuildSerializer(Serializer serializer, Type type, ConcurrentDictionary <Type, ValueSerializer> typeMapping) { var os = new ObjectSerializer(type); if (serializer.Options.KnownTypesDict.TryGetValue(type, out var index)) { var wrapper = new KnownTypeObjectSerializer(os, index); typeMapping.TryAdd(type, wrapper); } else { typeMapping.TryAdd(type, os); } var methodInfoSerializer = serializer.GetSerializerByType(typeof(MethodInfo)); var preserveObjectReferences = serializer.Options.PreserveObjectReferences; ObjectReader reader = (stream, session) => { var target = stream.ReadObject(session); var method = (MethodInfo)stream.ReadObject(session); var del = method.CreateDelegate(type, target); return(del); }; ObjectWriter writer = (stream, value, session) => { var d = (Delegate)value; var method = d.GetMethodInfo(); stream.WriteObjectWithManifest(d.Target, session); //less lookups, slightly faster stream.WriteObject(method, type, methodInfoSerializer, preserveObjectReferences, session); }; os.Initialize(reader, writer); return(os); }
public override ValueSerializer BuildSerializer(Serializer serializer, Type type, ConcurrentDictionary <Type, ValueSerializer> typeMapping) { var exceptionSerializer = new ObjectSerializer(type); var hasDefaultConstructor = type.GetTypeInfo().GetConstructor(new Type[0]) != null; var createInstance = hasDefaultConstructor ? Activator.CreateInstance : GetUninitializedObject; exceptionSerializer.Initialize((stream, session) => { var exception = createInstance(type); var className = stream.ReadString(session); var message = stream.ReadString(session); var remoteStackTraceString = stream.ReadString(session); var stackTraceString = stream.ReadString(session); var innerException = stream.ReadObject(session); #if NETSTANDARD20 _className?.SetValue(exception, className); #else _className.SetValue(exception, className); #endif _message.SetValue(exception, message); _remoteStackTraceString.SetValue(exception, remoteStackTraceString); _stackTraceString.SetValue(exception, stackTraceString); _innerException.SetValue(exception, innerException); return(exception); }, (stream, exception, session) => { #if NETSTANDARD20 var className = (string)_className?.GetValue(exception); #else var className = (string)_className.GetValue(exception); #endif var message = (string)_message.GetValue(exception); var remoteStackTraceString = (string)_remoteStackTraceString.GetValue(exception); var stackTraceString = (string)_stackTraceString.GetValue(exception); var innerException = _innerException.GetValue(exception); StringSerializer.WriteValueImpl(stream, className, session); StringSerializer.WriteValueImpl(stream, message, session); StringSerializer.WriteValueImpl(stream, remoteStackTraceString, session); StringSerializer.WriteValueImpl(stream, stackTraceString, session); stream.WriteObjectWithManifest(innerException, session); }); if (serializer.Options.KnownTypesDict.TryGetValue(type, out var index)) { var wrapper = new KnownTypeObjectSerializer(exceptionSerializer, index); typeMapping.TryAdd(type, wrapper); } else { typeMapping.TryAdd(type, exceptionSerializer); } return(exceptionSerializer); }
public override ValueSerializer BuildSerializer(Serializer serializer, Type type, ConcurrentDictionary <Type, ValueSerializer> typeMapping) { var ser = new ObjectSerializer(type); if (serializer.Options.KnownTypesDict.TryGetValue(type, out var index)) { var wrapper = new KnownTypeObjectSerializer(ser, index); typeMapping.TryAdd(type, wrapper); } else { typeMapping.TryAdd(type, ser); } var elementSerializer = serializer.GetSerializerByType(typeof(DictionaryEntry)); var preserveObjectReferences = serializer.Options.PreserveObjectReferences; ObjectReader reader = (stream, session) => { var count = stream.ReadInt32(session); var instance = (IDictionary)Activator.CreateInstance(type, count); if (preserveObjectReferences) { session.TrackDeserializedObject(instance); } for (var i = 0; i < count; i++) { var entry = (DictionaryEntry)stream.ReadObject(session); instance.Add(entry.Key, entry.Value); } return(instance); }; ObjectWriter writer = (stream, obj, session) => { if (preserveObjectReferences) { session.TrackSerializedObject(obj); } var dict = obj as IDictionary; // ReSharper disable once PossibleNullReferenceException Int32Serializer.WriteValueImpl(stream, dict.Count, session); foreach (DictionaryEntry item in dict) { stream.WriteObject(item, typeof(DictionaryEntry), elementSerializer, serializer.Options.PreserveObjectReferences, session); // elementSerializer.WriteValue(stream,item,session); } }; ser.Initialize(reader, writer); return(ser); }
public override ValueSerializer BuildSerializer(Serializer serializer, Type type, ConcurrentDictionary <Type, ValueSerializer> typeMapping) { var arraySerializer = new ObjectSerializer(type); var elementType = type.GetElementType(); var elementSerializer = serializer.GetSerializerByType(elementType); var preserveObjectReferences = serializer.Options.PreserveObjectReferences; //TODO: code gen this part ObjectReader reader = (stream, session) => { var length = stream.ReadInt32(session); var array = Array.CreateInstance(elementType, length); //create the array if (preserveObjectReferences) { session.TrackDeserializedObject(array); } ReadValues(length, stream, session, (dynamic)array); return(array); }; ObjectWriter writer = (stream, arr, session) => { if (preserveObjectReferences) { session.TrackSerializedObject(arr); } WriteValues((dynamic)arr, stream, elementType, elementSerializer, session); }; arraySerializer.Initialize(reader, writer); if (serializer.Options.KnownTypesDict.TryGetValue(type, out var index)) { var wrapper = new KnownTypeObjectSerializer(arraySerializer, index); typeMapping.TryAdd(type, wrapper); } else { typeMapping.TryAdd(type, arraySerializer); } return(arraySerializer); }
public override ValueSerializer BuildSerializer(Serializer serializer, Type type, ConcurrentDictionary <Type, ValueSerializer> typeMapping) { var arraySerializer = new ObjectSerializer(type); var elementType = type.GetTypeInfo() .GetMethods() .Where(methodInfo => methodInfo.Name == "Get") .Select(methodInfo => methodInfo.ReturnType) .FirstOrDefault(); var elementSerializer = serializer.GetSerializerByType(elementType); var preserveObjectReferences = serializer.Options.PreserveObjectReferences; var arrayRank = type.GetArrayRank(); //TODO: code gen this part ObjectReader reader = CreateReader(preserveObjectReferences, arrayRank, elementType); ObjectWriter writer = (stream, arr, session) => { if (preserveObjectReferences) { session.TrackSerializedObject(arr); } WriteValues((Array)arr, stream, elementType, elementSerializer, session); }; arraySerializer.Initialize(reader, writer); if (serializer.Options.KnownTypesDict.TryGetValue(type, out var index)) { var wrapper = new KnownTypeObjectSerializer(arraySerializer, index); typeMapping.TryAdd(type, wrapper); } else { typeMapping.TryAdd(type, arraySerializer); } return(arraySerializer); }
public ValueSerializer GetSerializerByType([NotNull] Type type) { //do we already have a serializer for this type? if (_serializers.TryGetValue(type, out var serializer)) { return(serializer); } //is there a serializer factory that can handle this type? foreach (var valueSerializerFactory in Options.ValueSerializerFactories) { if (valueSerializerFactory.CanSerialize(this, type)) { return(valueSerializerFactory.BuildSerializer(this, type, _serializers)); } } //none of the above, lets create a POCO object serializer serializer = new ObjectSerializer(type); if (Options.KnownTypesDict.TryGetValue(type, out var index)) { var wrapper = new KnownTypeObjectSerializer((ObjectSerializer)serializer, index); if (!_serializers.TryAdd(type, wrapper)) { return(_serializers[type]); } try { //build the serializer IL code CodeGenerator.BuildSerializer(this, (ObjectSerializer)serializer); } catch (Exception exp) { var invalidSerializer = new UnsupportedTypeSerializer(type, exp.Message); _serializers[type] = invalidSerializer; return(invalidSerializer); } //just ignore if this fails, another thread have already added an identical serializer return(wrapper); } if (!_serializers.TryAdd(type, serializer)) { return(_serializers[type]); } try { //build the serializer IL code CodeGenerator.BuildSerializer(this, (ObjectSerializer)serializer); } catch (Exception exp) { var invalidSerializer = new UnsupportedTypeSerializer(type, exp.Message); _serializers[type] = invalidSerializer; return(invalidSerializer); } //just ignore if this fails, another thread have already added an identical serializer return(serializer); //add it to the serializer lookup in case of recursive serialization }
public override ValueSerializer BuildSerializer(Serializer serializer, Type type, ConcurrentDictionary <Type, ValueSerializer> typeMapping) { var x = new ObjectSerializer(type); if (serializer.Options.KnownTypesDict.TryGetValue(type, out var index)) { var wrapper = new KnownTypeObjectSerializer(x, index); typeMapping.TryAdd(type, wrapper); } else { typeMapping.TryAdd(type, x); } var preserveObjectReferences = serializer.Options.PreserveObjectReferences; var elementType = GetEnumerableType(type) ?? typeof(object); var elementSerializer = serializer.GetSerializerByType(elementType); var typeName = type.Name; var genericSufixIdx = typeName.IndexOf('`'); typeName = genericSufixIdx != -1 ? typeName.Substring(0, genericSufixIdx) : typeName; var creatorType = Type.GetType(ImmutableCollectionsNamespace + "." + typeName + ", " + ImmutableCollectionsAssembly); var createRangeMethodInfo = creatorType != null ? creatorType.GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.Static) .First(methodInfo => methodInfo.Name == "CreateRange" && methodInfo.GetParameters().Length == 1) : null; // If the element type is a generic type and the method located to create the collection instance requires more than one generic type parameter // we need to obtain the generic arguments of the element type. var genericTypes = elementType.GetTypeInfo().IsGenericType&& createRangeMethodInfo != null && createRangeMethodInfo.GetGenericArguments().Length > 1 ? elementType.GetTypeInfo().GetGenericArguments() : new[] { elementType }; // if creatorType == null it means that type is probably an interface // we propagate null to create mock serializer - it won't be used anyway var stackTypeDef = Type.GetType(ImmutableCollectionsNamespace + ".IImmutableStack`1, " + ImmutableCollectionsAssembly, true); var stackInterface = stackTypeDef.MakeGenericType(genericTypes[0]); var isStack = stackInterface.IsAssignableFrom(type); var createRange = createRangeMethodInfo != null ? createRangeMethodInfo.MakeGenericMethod(genericTypes) : null; ObjectWriter writer = (stream, o, session) => { var enumerable = o as ICollection; if (enumerable == null) { // object can be IEnumerable but not ICollection i.e. ImmutableQueue var e = (IEnumerable)o; var list = e.Cast <object>().ToList();// enumerable = list; } Int32Serializer.WriteValueImpl(stream, enumerable.Count, session); foreach (var value in enumerable) { stream.WriteObject(value, elementType, elementSerializer, preserveObjectReferences, session); } if (preserveObjectReferences) { session.TrackSerializedObject(o); } }; ObjectReader reader; if (isStack) { // if we are dealing with stack, we need to apply arguments in reverse order reader = (stream, session) => { var count = stream.ReadInt32(session); var items = Array.CreateInstance(elementType, count); for (var i = 0; i < count; i++) { var value = stream.ReadObject(session); items.SetValue(value, count - i - 1); } var instance = createRange.Invoke(null, new object[] { items }); if (preserveObjectReferences) { session.TrackDeserializedObject(instance); } return(instance); }; } else { reader = (stream, session) => { var count = stream.ReadInt32(session); var items = Array.CreateInstance(elementType, count); for (var i = 0; i < count; i++) { var value = stream.ReadObject(session); items.SetValue(value, i); } var instance = createRange.Invoke(null, new object[] { items }); if (preserveObjectReferences) { session.TrackDeserializedObject(instance); } return(instance); }; } x.Initialize(reader, writer); return(x); }