public bool HasFieldSerializer(Type type) { if (type.IsValueType) { var hasSerializeMethod = ValueTypeSerializeMethods.GetMethodForType(type) != null; Debug.Assert(hasSerializeMethod == (ValueTypeDeserializeMethods.GetMethodForType(type) != null)); // <- debug check for matching deserializer return(hasSerializeMethod); } else { var hasSerializeMethod = ReferenceFieldSerializeMethods.GetMethodForType(type) != null; Debug.Assert(hasSerializeMethod == (ReferenceFieldDeserializeMethods.GetMethodForType(type) != null)); // <- debug check for matching deserializer return(hasSerializeMethod); } }
// Field serializers are always "byref" so they will always have the same signature, taking a "ref T", for both reference and value types. // Value-type serializers continue to work as-is as field serializers (always byref) // Reference field deserialize is already taking a reference type byref // Reference field serialize just takes a reference, so must be wrapped so the delegate can take a reference byref public FieldSerializeMethod <T> GetFieldSerializeDelegate <T>() { if (typeof(T).IsValueType) { var method = ValueTypeSerializeMethods.GetMethodForType(typeof(T)); Debug.Assert(method != null); return((FieldSerializeMethod <T>)CreateDelegate(typeof(FieldSerializeMethod <T>), method)); } else { var method = ReferenceFieldSerializeMethods.GetMethodForType(typeof(T)); Debug.Assert(method != null); // Normal reference field serializers don't take a 'byref' parameter, so we must create a wrapper so the external signature matches: var serializeField = (Action <SerializeContext, BinaryWriter, T>)CreateDelegate( typeof(Action <SerializeContext, BinaryWriter, T>), method); FieldSerializeMethod <T> wrapper = (SerializeContext context, BinaryWriter bw, ref T obj) => serializeField(context, bw, obj); return(wrapper); } }