internal void ResolveListTypes(Type type, ref Type itemType, ref Type defaultType) { if (type == null) { return; } if (Helpers.GetTypeCode(type) != ProtoTypeCode.Unknown) { return; } if (this[type].IgnoreListHandling) { return; } if (type.IsArray) { if (type.GetArrayRank() != 1) { throw new NotSupportedException("Multi-dimension arrays are supported"); } itemType = type.GetElementType(); if (itemType == base.MapType(typeof(byte))) { Type type2; itemType = (type2 = null); defaultType = type2; } else { defaultType = type; } } if (itemType == null) { itemType = TypeModel.GetListItemType(this, type); } if (itemType != null) { Type nestedItemType = null; Type nestedDefaultType = null; this.ResolveListTypes(itemType, ref nestedItemType, ref nestedDefaultType); if (nestedItemType != null) { throw TypeModel.CreateNestedListsNotSupported(); } } if (itemType != null && defaultType == null) { if (type.IsClass && !type.IsAbstract && Helpers.GetConstructor(type, Helpers.EmptyTypes, true) != null) { defaultType = type; } if (defaultType == null && type.IsInterface) { Type[] genArgs; if (type.IsGenericType && type.GetGenericTypeDefinition() == base.MapType(typeof(IDictionary <,>)) && itemType == base.MapType(typeof(KeyValuePair <,>)).MakeGenericType(genArgs = type.GetGenericArguments())) { defaultType = base.MapType(typeof(Dictionary <,>)).MakeGenericType(genArgs); } else { defaultType = base.MapType(typeof(List <>)).MakeGenericType(new Type[] { itemType }); } } if (defaultType != null && !Helpers.IsAssignableFrom(type, defaultType)) { defaultType = null; } } }
internal int FindOrAddAuto(Type type, bool demand, bool addWithContractOnly, bool addEvenIfAutoDisabled) { int key = this.types.IndexOf(RuntimeTypeModel.MetaTypeFinder, type); if (key >= 0) { MetaType metaType = (MetaType)this.types[key]; if (metaType.Pending) { this.WaitOnLock(metaType); } return(key); } bool shouldAdd = this.AutoAddMissingTypes || addEvenIfAutoDisabled; if (Helpers.IsEnum(type) || this.TryGetBasicTypeSerializer(type) == null) { Type underlyingType = TypeModel.ResolveProxies(type); if (underlyingType != null) { key = this.types.IndexOf(RuntimeTypeModel.MetaTypeFinder, underlyingType); type = underlyingType; } if (key < 0) { int opaqueToken = 0; try { this.TakeLock(ref opaqueToken); MetaType metaType; if ((metaType = this.RecogniseCommonTypes(type)) == null) { MetaType.AttributeFamily family = MetaType.GetContractFamily(this, type, null); if (family == MetaType.AttributeFamily.AutoTuple) { addEvenIfAutoDisabled = (shouldAdd = true); } if (!shouldAdd || (!Helpers.IsEnum(type) && addWithContractOnly && family == MetaType.AttributeFamily.None)) { if (demand) { TypeModel.ThrowUnexpectedType(type); } return(key); } metaType = this.Create(type); } metaType.Pending = true; bool weAdded = false; int winner = this.types.IndexOf(RuntimeTypeModel.MetaTypeFinder, type); if (winner < 0) { this.ThrowIfFrozen(); key = this.types.Add(metaType); weAdded = true; } else { key = winner; } if (weAdded) { metaType.ApplyDefaultBehaviour(); metaType.Pending = false; } } finally { this.ReleaseLock(opaqueToken); } return(key); } return(key); } if (shouldAdd && !addWithContractOnly) { throw MetaType.InbuiltType(type); } return(-1); }
public MetaType Add(Type type, bool applyDefaultBehaviour) { if (type == null) { throw new ArgumentNullException("type"); } MetaType newType = this.FindWithoutAdd(type); if (newType != null) { return(newType); } int opaqueToken = 0; if (type.IsInterface && base.MapType(MetaType.ienumerable).IsAssignableFrom(type) && TypeModel.GetListItemType(this, type) == null) { throw new ArgumentException("IEnumerable[<T>] data cannot be used as a meta-type unless an Add method can be resolved"); } try { newType = this.RecogniseCommonTypes(type); if (newType != null) { if (!applyDefaultBehaviour) { throw new ArgumentException("Default behaviour must be observed for certain types with special handling; " + type.FullName, "applyDefaultBehaviour"); } applyDefaultBehaviour = false; } if (newType == null) { newType = this.Create(type); } newType.Pending = true; this.TakeLock(ref opaqueToken); if (this.FindWithoutAdd(type) != null) { throw new ArgumentException("Duplicate type", "type"); } this.ThrowIfFrozen(); this.types.Add(newType); if (applyDefaultBehaviour) { newType.ApplyDefaultBehaviour(); } newType.Pending = false; } finally { this.ReleaseLock(opaqueToken); } return(newType); }
private void CascadeDependents(BasicList list, MetaType metaType) { if (metaType.IsList) { Type itemType = TypeModel.GetListItemType(this, metaType.Type); WireType defaultWireType; if (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, itemType, out defaultWireType, false, false, false, false) == null) { int index = this.FindOrAddAuto(itemType, false, false, false); if (index >= 0) { MetaType tmp = ((MetaType)this.types[index]).GetSurrogateOrBaseOrSelf(false); if (!list.Contains(tmp)) { list.Add(tmp); this.CascadeDependents(list, tmp); return; } } } } else { MetaType tmp; if (metaType.IsAutoTuple) { MemberInfo[] mapping; if (MetaType.ResolveTupleConstructor(metaType.Type, out mapping) != null) { for (int i = 0; i < mapping.Length; i++) { Type type = null; if (mapping[i] is PropertyInfo) { type = ((PropertyInfo)mapping[i]).PropertyType; } else { if (mapping[i] is FieldInfo) { type = ((FieldInfo)mapping[i]).FieldType; } } WireType defaultWireType2; if (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type, out defaultWireType2, false, false, false, false) == null) { int index2 = this.FindOrAddAuto(type, false, false, false); if (index2 >= 0) { tmp = ((MetaType)this.types[index2]).GetSurrogateOrBaseOrSelf(false); if (!list.Contains(tmp)) { list.Add(tmp); this.CascadeDependents(list, tmp); } } } } } } else { foreach (ValueMember member in metaType.Fields) { Type type2 = member.ItemType; if (type2 == null) { type2 = member.MemberType; } WireType defaultWireType3; if (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type2, out defaultWireType3, false, false, false, false) == null) { int index3 = this.FindOrAddAuto(type2, false, false, false); if (index3 >= 0) { tmp = ((MetaType)this.types[index3]).GetSurrogateOrBaseOrSelf(false); if (!list.Contains(tmp)) { list.Add(tmp); this.CascadeDependents(list, tmp); } } } } } if (metaType.HasSubtypes) { SubType[] subtypes = metaType.GetSubtypes(); for (int j = 0; j < subtypes.Length; j++) { SubType subType = subtypes[j]; tmp = subType.DerivedType.GetSurrogateOrSelf(); if (!list.Contains(tmp)) { list.Add(tmp); this.CascadeDependents(list, tmp); } } } tmp = metaType.BaseType; if (tmp != null) { tmp = tmp.GetSurrogateOrSelf(); } if (tmp != null && !list.Contains(tmp)) { list.Add(tmp); this.CascadeDependents(list, tmp); } } }