private void AddItem(MemberInfo m, CommonOptions options, bool must, bool all) { var ia = new ItemAttrs(m, Options, all ? AllOptionality : YuzuItemOptionality.None); if (ia.Count == 0) { if (must) { throw Error("Item {0} must be serialized", m.Name); } return; } if (ia.Count != 1) { throw Error("More than one of optional, required and member attributes for field '{0}'", m.Name); } var attrs = Options.GetItem(m); var serializeCond = attrs.Attr(Options.SerializeConditionAttribute); var item = new Item { Alias = Options.GetAlias(ia.Any()) ?? m.Name, IsOptional = ia.Required == null, IsCompact = attrs.HasAttr(Options.CompactAttribute), IsCopyable = attrs.HasAttr(Options.CopyableAttribute), IsMember = ia.Member != null, SerializeCond = serializeCond != null? Options.GetSerializeCondition(serializeCond, Type) : null, SerializeIfMethod = serializeCond != null? Options.GetSerializeMethod(serializeCond, Type) : null, DefaultValue = serializeCond != null? Options.GetDefault(serializeCond) : YuzuNoDefault.NoDefault, Name = m.Name, }; if (!item.IsOptional) { RequiredCount += 1; } var merge = attrs.HasAttr(Options.MergeAttribute); switch (m.MemberType) { case MemberTypes.Field: var f = m as FieldInfo; if (!f.IsPublic) { throw Error("Non-public item '{0}'", f.Name); } item.Type = f.FieldType; item.GetValue = f.GetValue; if (!merge) { item.SetValue = f.SetValue; } item.FieldInfo = f; break; case MemberTypes.Property: var p = m as PropertyInfo; var getter = p.GetGetMethod(); if (getter == null) { throw Error("No getter for item '{0}'", p.Name); } item.Type = p.PropertyType; var setter = p.GetSetMethod(); #if iOS // Apple forbids code generation. item.GetValue = obj => p.GetValue(obj, Utils.ZeroObjects); if (!merge && setter != null) { item.SetValue = (obj, value) => p.SetValue(obj, value, Utils.ZeroObjects); } #else if (Utils.IsStruct(Type)) { item.GetValue = obj => p.GetValue(obj, Utils.ZeroObjects); if (!merge && setter != null) { item.SetValue = (obj, value) => p.SetValue(obj, value, Utils.ZeroObjects); } } else { item.GetValue = BuildGetter(getter); if (!merge && setter != null) { item.SetValue = BuildSetter(setter); } } #endif item.PropInfo = p; break; default: throw Error("Member type {0} not supported", m.MemberType); } if (item.SetValue == null) { if (!item.Type.IsClass && !item.Type.IsInterface || item.Type == typeof(object)) { throw Error("Unable to either set or merge item {0}", item.Name); } } var over = Options.GetOverride(item.Type); if (over.HasAttr(Options.CompactAttribute)) { item.IsCompact = true; } if (!over.HasAttr(Options.CopyableAttribute)) { CheckCopyable(item.Type, options); } if (ia.Member != null && item.SerializeCond == null && !Type.IsAbstract && !Type.IsInterface) { item.SerializeCond = GetSerializeIf(item, options); } Items.Add(item); }
private void AddItem(MemberInfo m, bool must, bool all) { var ia = new ItemAttrs(m, Options, all ? AllOptionality : YuzuItemOptionality.None); if (ia.Count == 0) { if (must) { throw Error("Item {0} must be serialized", m.Name); } return; } if (ia.Count != 1) { throw Error("More than one of optional, required and member attributes for field '{0}'", m.Name); } var serializeIf = m.GetCustomAttribute_Compat(Options.SerializeIfAttribute, true); var item = new Item { Alias = Options.GetAlias(ia.Any()) ?? m.Name, IsOptional = ia.Required == null, IsCompact = m.IsDefined(Options.CompactAttribute, false), SerializeIf = serializeIf != null?Options.GetSerializeCondition(serializeIf) : null, Name = m.Name, }; var merge = m.IsDefined(Options.MergeAttribute, false); switch (m.MemberType) { case MemberTypes.Field: var f = m as FieldInfo; if (!f.IsPublic) { throw Error("Non-public item '{0}'", f.Name); } item.Type = f.FieldType; item.GetValue = f.GetValue; if (!merge) { item.SetValue = f.SetValue; } item.FieldInfo = f; break; case MemberTypes.Property: var p = m as PropertyInfo; var getter = p.GetGetMethod(); if (getter == null) { throw Error("No getter for item '{0}'", p.Name); } item.Type = p.PropertyType; var setter = p.GetSetMethod(); #if iOS // Apple forbids code generation. item.GetValue = obj => p.GetValue(obj, Utils.ZeroObjects); if (!merge && setter != null) { item.SetValue = (obj, value) => p.SetValue(obj, value, Utils.ZeroObjects); } #else if (Utils.IsStruct(Type)) { item.GetValue = obj => p.GetValue(obj, Utils.ZeroObjects); if (!merge && setter != null) { item.SetValue = (obj, value) => p.SetValue(obj, value, Utils.ZeroObjects); } } else { item.GetValue = BuildGetter(getter); if (!merge && setter != null) { item.SetValue = BuildSetter(setter); } } #endif item.PropInfo = p; break; default: throw Error("Member type {0} not supported", m.MemberType); } if (item.SetValue == null) { if (!item.Type.IsClass && !item.Type.IsInterface || item.Type == typeof(object)) { throw Error("Unable to either set or merge item {0}", item.Name); } } if (item.Type.IsDefined(Options.CompactAttribute, false)) { item.IsCompact = true; } if (ia.Member != null && item.SerializeIf == null && !Type.IsAbstract && !Type.IsInterface) { if (Default == null) { Default = Activator.CreateInstance(Type); } var d = item.GetValue(Default); var icoll = Utils.GetICollection(item.Type); if (d != null && icoll != null) { var mi = Utils.GetPrivateGeneric( GetType(), nameof(IsNonEmptyCollection), icoll.GetGenericArguments()[0]); item.SerializeIf = (Func <object, object, bool>) Delegate.CreateDelegate(typeof(Func <object, object, bool>), this, mi); } else { item.SerializeIf = (object obj, object value) => !Object.Equals(item.GetValue(obj), d); } } Items.Add(item); }