private PopulateDelegateSignature EmitPopulateDelegate() { // TODO Serialization: validate mappings array count var constructor = typeof(DeserializedDefinition <>).MakeGenericType(Type).GetConstructor(new[] { Type, typeof(DeserializedFieldEntry[]) }) ?? throw new NullReferenceException(); var valueParam = Expression.Parameter(typeof(object), "value"); var valueParamCast = Expression.Convert(valueParam, Type); var mappingParam = Expression.Parameter(typeof(DeserializedFieldEntry[]), "mapping"); var newExp = Expression.New(constructor, valueParamCast, mappingParam); var createDefinitionDelegate = Expression.Lambda <CreateDefinitionDelegate>(newExp, valueParam, mappingParam).Compile(); DeserializationResult PopulateDelegate( object target, DeserializedFieldEntry[] deserializedFields, object?[] defaultValues) { for (var i = 0; i < BaseFieldDefinitions.Length; i++) { var res = deserializedFields[i]; if (!res.Mapped) { continue; } var defValue = defaultValues[i]; if (Equals(res.Result?.RawValue, defValue)) { continue; } FieldAssigners[i](ref target, res.Result?.RawValue); } return(createDefinitionDelegate(target, deserializedFields)); } return(PopulateDelegate); }
// TODO Serialization: add skipHook private CopyDelegateSignature EmitCopyDelegate() { object CopyDelegate( object source, object target, ISerializationManager manager, ISerializationContext?context) { for (var i = 0; i < BaseFieldDefinitions.Length; i++) { var field = BaseFieldDefinitions[i]; var accessor = FieldAccessors[i]; var sourceValue = accessor(ref source); var targetValue = accessor(ref target); object?copy; if (sourceValue != null && targetValue != null && TypeHelpers.SelectCommonType(sourceValue.GetType(), targetValue.GetType()) == null) { copy = manager.CreateCopy(sourceValue, context); } else { copy = field.Attribute.CustomTypeSerializer != null ? manager.CopyWithTypeSerializer(field.Attribute.CustomTypeSerializer, sourceValue, targetValue, context) : manager.Copy(sourceValue, targetValue, context); } FieldAssigners[i](ref target, copy); } return(target); } return(CopyDelegate); }