protected override bool PrepareMember(MemberDescriptorBase member, MemberInfo metadataClassMemberInfo) { // Filter members if (member is PropertyDescriptor && ListOfMembersToRemove.Contains(member.OriginalName)) //if (member is PropertyDescriptor && (member.DeclaringType.Namespace ?? string.Empty).StartsWith(SystemCollectionsNamespace) && ListOfMembersToRemove.Contains(member.Name)) { return(false); } return(base.PrepareMember(member, metadataClassMemberInfo)); }
protected virtual bool PrepareMember(MemberDescriptorBase member, MemberInfo metadataClassMemberInfo) { var memberType = member.Type; // Start with DataContractAttribute.DefaultMemberMode (if set) member.Mode = DefaultMemberMode; member.Mask = 1; var attributes = AttributeRegistry.GetAttributes(member.MemberInfo); if (metadataClassMemberInfo != null) { var metadataAttributes = AttributeRegistry.GetAttributes(metadataClassMemberInfo); attributes.InsertRange(0, metadataAttributes); } // Gets the style var styleAttribute = attributes.FirstOrDefault(x => x is DataStyleAttribute) as DataStyleAttribute; if (styleAttribute != null) { member.Style = styleAttribute.Style; member.ScalarStyle = styleAttribute.ScalarStyle; } // Handle member attribute var memberAttribute = attributes.FirstOrDefault(x => x is DataMemberAttribute) as DataMemberAttribute; if (memberAttribute != null) { ((IMemberDescriptor)member).Mask = memberAttribute.Mask; if (!member.HasSet) { if (memberAttribute.Mode == DataMemberMode.Assign || (memberType.IsValueType && member.Mode == DataMemberMode.Content)) { throw new ArgumentException($"{memberType.FullName} {member.OriginalName} is not writeable by {memberAttribute.Mode.ToString()}."); } } member.Mode = memberAttribute.Mode; member.Order = memberAttribute.Order; } // If mode is Default, let's resolve to the actual mode depending on getter/setter existence and object type if (member.Mode == DataMemberMode.Default) { // The default mode is Content, which will not use the setter to restore value if the object is a class (but behave like Assign for value types) member.Mode = DataMemberMode.Content; if (!member.HasSet && (memberType == typeof(string) || !memberType.IsClass) && !memberType.IsInterface && !Type.IsAnonymous()) { // If there is no setter, and the value is a string or a value type, we won't write the object at all. member.Mode = DataMemberMode.Never; } } // Process all attributes just once instead of getting them one by one DefaultValueAttribute defaultValueAttribute = null; foreach (var attribute in attributes) { var valueAttribute = attribute as DefaultValueAttribute; if (valueAttribute != null) { // If we've already found one, don't overwrite it defaultValueAttribute = defaultValueAttribute ?? valueAttribute; continue; } var yamlRemap = attribute as DataAliasAttribute; if (yamlRemap != null) { if (member.AlternativeNames == null) { member.AlternativeNames = new List <string>(); } if (!string.IsNullOrWhiteSpace(yamlRemap.Name)) { member.AlternativeNames.Add(yamlRemap.Name); } } } // If it's a private member, check it has a YamlMemberAttribute on it if (!member.IsPublic) { if (memberAttribute == null) { return(false); } } if (member.Mode == DataMemberMode.Binary) { if (!memberType.IsArray) { throw new InvalidOperationException($"{memberType.FullName} {member.OriginalName} of {Type.FullName} is not an array. Can not be serialized as binary."); } if (!memberType.GetElementType().IsPureValueType()) { throw new InvalidOperationException($"{memberType.GetElementType()} is not a pure ValueType. {memberType.FullName} {member.OriginalName} of {Type.FullName} can not serialize as binary."); } } // If this member cannot be serialized, remove it from the list if (member.Mode == DataMemberMode.Never) { return(false); } // ShouldSerialize // YamlSerializeAttribute(Never) => false // ShouldSerializeSomeProperty => call it // DefaultValueAttribute(default) => compare to it // otherwise => true var shouldSerialize = Type.GetMethod("ShouldSerialize" + member.OriginalName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); if (shouldSerialize != null && shouldSerialize.ReturnType == typeof(bool) && member.ShouldSerialize == null) { member.ShouldSerialize = (obj, parentTypeMemberDesc) => (bool)shouldSerialize.Invoke(obj, EmptyObjectArray); } if (defaultValueAttribute != null && member.ShouldSerialize == null && !emitDefaultValues) { member.DefaultValueAttribute = defaultValueAttribute; object defaultValue = defaultValueAttribute.Value; Type defaultType = defaultValue?.GetType(); if (defaultType != null && defaultType.IsNumeric() && defaultType != memberType) { try { defaultValue = Convert.ChangeType(defaultValue, memberType); } catch (InvalidCastException) { } } member.ShouldSerialize = (obj, parentTypeMemberDesc) => { if (parentTypeMemberDesc?.HasDefaultValue ?? false) { var parentDefaultValue = parentTypeMemberDesc.DefaultValue; if (parentDefaultValue != null) { // The parent class holding this object type has defined it's own default value for this type var parentDefaultValueMemberValue = member.Get(parentDefaultValue); // This is the real default value for this object return(!Equals(parentDefaultValueMemberValue, member.Get(obj))); } } return(!Equals(defaultValue, member.Get(obj))); }; } if (member.ShouldSerialize == null) { member.ShouldSerialize = ShouldSerializeDefault; } member.Name = !string.IsNullOrEmpty(memberAttribute?.Name) ? memberAttribute.Name : NamingConvention.Convert(member.OriginalName); return(true); }