/// <summary> /// Gets a delegate which determines if the property or field should not be serialized based upon its value. /// </summary> /// <param name="member"></param> /// <returns>if has a value equivalent to the DefaultValueAttribute</returns> /// <remarks> /// This is useful for excluding serialization of default values. /// </remarks> public override ValueIgnoredDelegate GetValueIgnoredCallback(MemberInfo member) { Type objType = member.ReflectedType ?? member.DeclaringType; JsonSpecifiedPropertyAttribute specifiedPropertyAttr = TypeCoercionUtility.GetAttribute <JsonSpecifiedPropertyAttribute>(member); // look up specified property to see if exists GetterDelegate specifiedPropertyGetter = null; if (specifiedPropertyAttr != null && !String.IsNullOrEmpty(specifiedPropertyAttr.SpecifiedProperty)) { PropertyInfo specProp = objType.GetProperty(specifiedPropertyAttr.SpecifiedProperty, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); // ensure is correct return type if (specProp != null && specProp.PropertyType == typeof(bool)) { specifiedPropertyGetter = DynamicMethodGenerator.GetPropertyGetter(specProp); } } DefaultValueAttribute defaultAttr = TypeCoercionUtility.GetAttribute <DefaultValueAttribute>(member); if (defaultAttr == null) { if (specifiedPropertyGetter == null) { // no need to even create a delegate return(null); } // create a delegate which simply calls the specified property return(delegate(object target, object value) { return Object.Equals(false, specifiedPropertyGetter(target)); }); } // extract default value since cannot change (is constant in attribute) object defaultValue = defaultAttr.Value; if (specifiedPropertyGetter == null) { // create a specific delegate which only has to compare the default value to the current value return(delegate(object target, object value) { return Object.Equals(defaultValue, value); }); } // create a combined delegate which checks both states return(delegate(object target, object value) { return Object.Equals(defaultValue, value) || Object.Equals(false, specifiedPropertyGetter(target)); }); }
/// <summary> /// Gets the serialized name for the member. /// </summary> /// <param name="member"></param> /// <returns></returns> public override IEnumerable <DataName> GetName(MemberInfo member) { JsonNameAttribute attr = TypeCoercionUtility.GetAttribute <JsonNameAttribute>(member); // NOTE: JSON allows String.Empty as a valid property name if ((attr == null) || (attr.Name == null)) { yield break; } yield return(new DataName(attr.Name)); }
/// <summary> /// Gets the serialized name for the member. /// </summary> /// <param name="member"></param> /// <returns></returns> public override IEnumerable <DataName> GetName(MemberInfo member) { if (member is Type) { XmlRootAttribute rootAttr = TypeCoercionUtility.GetAttribute <XmlRootAttribute>(member); if (rootAttr != null && !String.IsNullOrEmpty(rootAttr.ElementName)) { yield return(new DataName(rootAttr.ElementName, null, rootAttr.Namespace)); } XmlTypeAttribute typeAttr = TypeCoercionUtility.GetAttribute <XmlTypeAttribute>(member); if (typeAttr != null && !String.IsNullOrEmpty(typeAttr.TypeName)) { yield return(new DataName(typeAttr.TypeName, null, typeAttr.Namespace)); } yield break; } XmlElementAttribute elemAttr = TypeCoercionUtility.GetAttribute <XmlElementAttribute>(member); if (elemAttr != null && !String.IsNullOrEmpty(elemAttr.ElementName)) { yield return(new DataName(elemAttr.ElementName, null, elemAttr.Namespace)); } XmlAttributeAttribute attrAttr = TypeCoercionUtility.GetAttribute <XmlAttributeAttribute>(member); if (attrAttr != null && !String.IsNullOrEmpty(attrAttr.AttributeName)) { yield return(new DataName(attrAttr.AttributeName, null, attrAttr.Namespace, true)); } XmlArrayAttribute arrayAttr = TypeCoercionUtility.GetAttribute <XmlArrayAttribute>(member); if (arrayAttr != null && !String.IsNullOrEmpty(arrayAttr.ElementName)) { // TODO: figure out a way to surface XmlArrayItemAttribute name too yield return(new DataName(arrayAttr.ElementName, null, arrayAttr.Namespace)); } if (member is FieldInfo && ((FieldInfo)member).DeclaringType.IsEnum) { XmlEnumAttribute enumAttr = TypeCoercionUtility.GetAttribute <XmlEnumAttribute>(member); if (enumAttr != null && !String.IsNullOrEmpty(enumAttr.Name)) { yield return(new DataName(enumAttr.Name)); } } }
/// <summary> /// Gets the serialized name for the member. /// </summary> /// <param name="member"></param> /// <returns></returns> public override IEnumerable <DataName> GetName(MemberInfo member) { string localName, ns; Attribute typeAttr; if (member is Type) { typeAttr = TypeCoercionUtility.GetAttribute(member, DataContractResolverStrategy.DataContractType); if (typeAttr == null) { yield break; } localName = (string)DataContractResolverStrategy.DataContractNameGetter(typeAttr); ns = (string)DataContractResolverStrategy.DataContractNamespaceGetter(typeAttr); if (!String.IsNullOrEmpty(localName)) { yield return(new DataName(localName, null, ns)); } yield break; } typeAttr = TypeCoercionUtility.GetAttribute(member.DeclaringType, DataContractResolverStrategy.DataContractType); if (typeAttr == null) { yield break; } ns = (string)DataContractResolverStrategy.DataContractNamespaceGetter(typeAttr); Attribute memberAttr = TypeCoercionUtility.GetAttribute(member, DataContractResolverStrategy.DataMemberType); if (memberAttr == null) { yield break; } localName = (string)DataContractResolverStrategy.DataMemberNameGetter(memberAttr); if (!String.IsNullOrEmpty(localName)) { // members inherit DataContract namespaces yield return(new DataName(localName, null, ns)); } }
/// <summary> /// Gets a delegate which determines if the property or field should not be serialized based upon its value. /// </summary> /// <param name="member"></param> /// <returns>if has a value equivalent to the DefaultValueAttribute or has a property named XXXSpecified which determines visibility</returns> /// <remarks> /// This is useful when default values need not be serialized. /// Under these situations XmlSerializer ignores properties based upon value: /// - DefaultValue: http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx /// - Specified Properies: http://msdn.microsoft.com/en-us/library/bb402199.aspx /// - ShouldSerialize Methods: http://msdn.microsoft.com/en-us/library/53b8022e.aspx /// </remarks> public override ValueIgnoredDelegate GetValueIgnoredCallback(MemberInfo member) { Type objType = member.ReflectedType ?? member.DeclaringType; // look up specified property to see if exists GetterDelegate specifiedPropertyGetter = null; PropertyInfo specProp = objType.GetProperty(member.Name + SpecifiedSuffix, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); // ensure is correct return type if (specProp != null && specProp.PropertyType == typeof(bool)) { specifiedPropertyGetter = DynamicMethodGenerator.GetPropertyGetter(specProp); } // look up specified property to see if exists ProxyDelegate shouldSerializeProxy = null; MethodInfo shouldSerialize = objType.GetMethod(ShouldSerializePrefix + member.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); // ensure is correct return type if (shouldSerialize != null && shouldSerialize.ReturnType == typeof(bool) && shouldSerialize.GetParameters().Length == 0) { shouldSerializeProxy = DynamicMethodGenerator.GetMethodProxy(shouldSerialize); } // to be most efficient must create a different delegate for each of 8 combinations so not performing extra work DefaultValueAttribute defaultAttr = TypeCoercionUtility.GetAttribute <DefaultValueAttribute>(member); if (defaultAttr == null) { if (specifiedPropertyGetter == null) { if (shouldSerializeProxy == null) { // situation 1: only need to check if equal to null return(delegate(object target, object value) { return (value == null); }); } // situation 2: create a delegate which simply calls the should serialize method return(delegate(object target, object value) { return (value == null) || Object.Equals(false, shouldSerializeProxy(target)); }); } if (shouldSerializeProxy == null) { // situation 3: create a delegate which simply calls the specified property return(delegate(object target, object value) { return (value == null) || Object.Equals(false, specifiedPropertyGetter(target)); }); } // situation 4: create a delegate which calls both the specified property and the should serialize method return(delegate(object target, object value) { return (value == null) || Object.Equals(false, shouldSerializeProxy(target)) || Object.Equals(false, specifiedPropertyGetter(target)); }); } // extract default value since cannot change (is constant in attribute) object defaultValue = defaultAttr.Value; if (specifiedPropertyGetter == null) { if (shouldSerializeProxy == null) { // situation 5: create a specific delegate which only has to compare the default value to the current value return(delegate(object target, object value) { return (value == null) || Object.Equals(defaultValue, value); }); } // situation 6: create a specific delegate which both compares to default value and calls should serialize method return(delegate(object target, object value) { return (value == null) || Object.Equals(defaultValue, value) || Object.Equals(false, shouldSerializeProxy(target)); }); } if (shouldSerializeProxy == null) { // situation 7: create a specific delegate which both compares to default value and checks specified property return(delegate(object target, object value) { return (value == null) || Object.Equals(defaultValue, value) || Object.Equals(false, specifiedPropertyGetter(target)); }); } // situation 8: create a combined delegate which checks all states return(delegate(object target, object value) { return (value == null) || Object.Equals(defaultValue, value) || Object.Equals(false, shouldSerializeProxy(target)) || Object.Equals(false, specifiedPropertyGetter(target)); }); }