diff --git a/YamlDotNet/Serialization/TypeInspectors/ReadableAndWritablePropertiesTypeInspector.cs b/YamlDotNet/Serialization/TypeInspectors/ReadableAndWritablePropertiesTypeInspector.cs index fce64cbe5..43b376cc6 100644 --- a/YamlDotNet/Serialization/TypeInspectors/ReadableAndWritablePropertiesTypeInspector.cs +++ b/YamlDotNet/Serialization/TypeInspectors/ReadableAndWritablePropertiesTypeInspector.cs @@ -39,8 +39,16 @@ public ReadableAndWritablePropertiesTypeInspector(ITypeInspector innerTypeDescri public override IEnumerable GetProperties(Type type, object? container) { - return innerTypeDescriptor.GetProperties(type, container) - .Where(p => p.CanWrite); + return innerTypeDescriptor + .GetProperties(type, container) + .Where(p => + p.CanWrite || + (p.Type.IsGenericType + && typeof(ICollection<>) + .MakeGenericType(p.Type.GenericTypeArguments[0]) + .IsAssignableFrom(p.Type) + ) + ); } } } diff --git a/YamlDotNet/Serialization/TypeInspectors/ReadablePropertiesTypeInspector.cs b/YamlDotNet/Serialization/TypeInspectors/ReadablePropertiesTypeInspector.cs index 3e78fbc56..a229473de 100644 --- a/YamlDotNet/Serialization/TypeInspectors/ReadablePropertiesTypeInspector.cs +++ b/YamlDotNet/Serialization/TypeInspectors/ReadablePropertiesTypeInspector.cs @@ -36,7 +36,7 @@ public sealed class ReadablePropertiesTypeInspector : TypeInspectorSkeleton private readonly bool includeNonPublicProperties; public ReadablePropertiesTypeInspector(ITypeResolver typeResolver) - :this(typeResolver, false) + : this(typeResolver, false) { } @@ -81,9 +81,33 @@ public ReflectionPropertyDescriptor(PropertyInfo propertyInfo, ITypeResolver typ public void Write(object target, object? value) { + if (!propertyInfo.CanWrite && value != null) + { + var propertyCurrentValue = propertyInfo.GetValue(target); + if (propertyCurrentValue != null) + { + var targetType = propertyInfo.PropertyType; + var valueType = value.GetType(); + if (targetType.IsGenericType && typeof(ICollection<>).MakeGenericType(targetType.GenericTypeArguments[0]).IsAssignableFrom(targetType) + && valueType.IsGenericType && typeof(ICollection<>).MakeGenericType(valueType.GenericTypeArguments[0]).IsAssignableFrom(valueType)) + { + var copyMethod = typeof(ReflectionPropertyDescriptor).GetMethod(nameof(CopyCollection))!.MakeGenericMethod(targetType.GenericTypeArguments[0]); + copyMethod.Invoke(null, new object[] { propertyCurrentValue, value }); + return; + } + } + } propertyInfo.SetValue(target, value, null); } + public static void CopyCollection(ICollection target, ICollection source) + { + foreach (var element in source) + { + target.Add(element); + } + } + public T GetCustomAttribute() where T : Attribute { var attributes = propertyInfo.GetAllCustomAttributes();