private Meta(Type t, CommonOptions options) { Type = t; Factory = defaultFactory; Options = options.Meta ?? MetaOptions.Default; IsCopyable = Utils.IsStruct(t); var over = Options.GetOverride(t); IsCompact = over.HasAttr(Options.CompactAttribute); var must = over.Attr(Options.MustAttribute); if (must != null) { Must = Options.GetItemKind(must); } var all = over.Attr(Options.AllAttribute); if (all != null) { var ok = Options.GetItemOptionalityAndKind(all); AllOptionality = ok.Item1; AllKind = ok.Item2; } Surrogate = new Surrogate(Type, Options); foreach (var i in t.GetInterfaces()) { ExploreType(i, options); } ExploreType(t, options); Surrogate.Complete(); CheckForNoFields(options); Items.Sort(); Item prev = null; foreach (var i in Items) { if (prev != null && prev.CompareTo(i) == 0) { throw Error("Duplicate item {0} / {1}", i.Name, i.Alias); } prev = i; } var prevTag = ""; foreach (var i in Items) { var tag = i.Tag(options); if (tag == "") { throw Error("Empty tag for field '{0}'", i.Name); } foreach (var ch in tag) { if (ch <= ' ' || ch >= 127) { throw Error("Bad character '{0}' in tag for field '{1}'", ch, i.Name); } } if (tag == prevTag) { throw Error("Duplicate tag '{0}' for field '{1}'", tag, i.Name); } prevTag = tag; TagToItem.Add(tag, i); } AllowReadingFromAncestor = over.HasAttr(Options.AllowReadingFromAncestorAttribute); if (AllowReadingFromAncestor) { var ancestorMeta = Get(t.BaseType, options); if (ancestorMeta.Items.Count != Items.Count) { throw Error( "Allows reading from ancestor {0}, but has {1} items instead of {2}", t.BaseType.Name, Items.Count, ancestorMeta.Items.Count); } } var alias = over.Attr(Options.AliasAttribute); if (alias != null) { var aliases = Options.GetReadAliases(alias); if (aliases != null) { Dictionary <string, Type> readAliases = readAliasCache.GetOrAdd(options, MakeReadAliases); foreach (var a in aliases) { if (String.IsNullOrWhiteSpace(a)) { throw Error("Empty read alias"); } Type duplicate; if (readAliases.TryGetValue(a, out duplicate)) { throw Error("Read alias '{0}' was already defined for '{1}'", a, duplicate.Name); } readAliases.Add(a, t); } } WriteAlias = Options.GetWriteAlias(alias); if (WriteAlias != null && WriteAlias == "") { throw Error("Empty write alias"); } } if (over.HasAttr(Options.CopyableAttribute)) { IsCopyable = true; } else if (HasAnyTrigger()) { IsCopyable = false; } }
private Meta(Type t, CommonOptions options) { Type = t; Options = options.Meta ?? MetaOptions.Default; IsCompact = t.IsDefined(Options.CompactAttribute, false); var must = t.GetCustomAttribute_Compat(Options.MustAttribute, false); if (must != null) { Must = Options.GetItemKind(must); } var all = t.GetCustomAttribute_Compat(Options.AllAttribute, false); if (all != null) { var ok = Options.GetItemOptionalityAndKind(all); AllOptionality = ok.Item1; AllKind = ok.Item2; } Surrogate = new Surrogate(Type, Options); foreach (var i in t.GetInterfaces()) { ExploreType(i); } ExploreType(t); Surrogate.Complete(); if (Utils.GetICollection(t) != null) { if (Items.Count > 0) { throw Error("Serializable fields in collection are not supported"); } } else if ( !options.AllowEmptyTypes && Items.Count == 0 && !(t.IsInterface || t.IsAbstract) && Surrogate.SurrogateType == null ) { throw Error("No serializable fields"); } Items.Sort(); Item prev = null; foreach (var i in Items) { if (prev != null && prev.CompareTo(i) == 0) { throw Error("Duplicate item {0} / {1}", i.Name, i.Alias); } prev = i; } var prevTag = ""; foreach (var i in Items) { var tag = i.Tag(options); if (tag == "") { throw Error("Empty tag for field '{0}'", i.Name); } foreach (var ch in tag) { if (ch <= ' ' || ch >= 127) { throw Error("Bad character '{0}' in tag for field '{1}'", ch, i.Name); } } if (tag == prevTag) { throw Error("Duplicate tag '{0}' for field '{1}'", tag, i.Name); } prevTag = tag; TagToItem.Add(tag, i); } AllowReadingFromAncestor = t.IsDefined(Options.AllowReadingFromAncestorAttribute, false); if (AllowReadingFromAncestor) { var ancestorMeta = Get(t.BaseType, options); if (ancestorMeta.Items.Count != Items.Count) { throw Error( "Allows reading from ancestor {0}, but has {1} items instead of {2}", t.BaseType.Name, Items.Count, ancestorMeta.Items.Count); } } var alias = t.GetCustomAttribute_Compat(Options.AliasAttribute, false); if (alias != null) { var aliases = Options.GetReadAliases(alias); if (aliases != null) { Dictionary <string, Type> readAliases; if (!readAliasCache.TryGetValue(options, out readAliases)) { readAliases = new Dictionary <string, Type>(); readAliasCache.Add(options, readAliases); } foreach (var a in aliases) { try { if (String.IsNullOrWhiteSpace(a)) { throw Error("Empty read alias"); } readAliases.Add(a, t); } catch (ArgumentException) { throw Error("Duplicate read alias '{0}'", a); } } } WriteAlias = Options.GetWriteAlias(alias); if (WriteAlias != null && WriteAlias == "") { throw Error("Empty write alias"); } } }