private static void TestEnumerableListPatterns(TypeModel model, BasicList candidates, Type iType) { #if WINRT TypeInfo iTypeInfo = iType.GetTypeInfo(); if (iTypeInfo.IsGenericType) { Type typeDef = iTypeInfo.GetGenericTypeDefinition(); if (typeDef == typeof(System.Collections.Generic.ICollection <>) || typeDef.GetTypeInfo().FullName == "System.Collections.Concurrent.IProducerConsumerCollection`1") { Type[] iTypeArgs = iTypeInfo.GenericTypeArguments; if (!candidates.Contains(iTypeArgs[0])) { candidates.Add(iTypeArgs[0]); } } } #elif !NO_GENERICS if (iType.IsGenericType) { Type typeDef = iType.GetGenericTypeDefinition(); if (typeDef == model.MapType(typeof(System.Collections.Generic.IEnumerable <>)) || typeDef == model.MapType(typeof(System.Collections.Generic.ICollection <>)) || typeDef.FullName == "System.Collections.Concurrent.IProducerConsumerCollection`1") { Type[] iTypeArgs = iType.GetGenericArguments(); if (!candidates.Contains(iTypeArgs[0])) { candidates.Add(iTypeArgs[0]); } } } #endif }
internal static BasicList GetContiguousGroups(int[] keys, object[] values) { if (keys == null) { throw new ArgumentNullException(nameof(keys)); } if (values == null) { throw new ArgumentNullException(nameof(values)); } if (values.Length < keys.Length) { throw new ArgumentException("Not all keys are covered by values", nameof(values)); } BasicList outer = new BasicList(); Group group = null; for (int i = 0; i < keys.Length; i++) { if (i == 0 || keys[i] != keys[i - 1]) { group = null; } if (group == null) { group = new Group(keys[i]); outer.Add(group); } group.Items.Add(values[i]); } return(outer); }
void CscadeDependents_Member(BasicList list, Type type) { WireType defaultWireType; IProtoSerializer coreSerializer = this.ValueSerializerBuilder.TryGetSimpleCoreSerializer(BinaryDataFormat.Default, type, out defaultWireType); if (coreSerializer == null) { int index = FindOrAddAuto(type, false, false, false); if (index >= 0) { var tmp = ((MetaType)_types[index]).GetSurrogateOrBaseOrSelf(false); if (!list.Contains(tmp)) { // could perhaps also implement as a queue, but this should work OK for sane models list.Add(tmp); CascadeDependents(list, tmp); } } } }
private IProtoTypeSerializer BuildSerializer(bool isRoot) { // reference tracking decorators (RootDecorator, NetObjectDecorator, NetObjectValueDecorator) // should always be applied only one time (otherwise will consider new objects as already written): // #1 For collection types references are handled either by RootDecorator or // by ValueMember which owns the value (so outside of this scope) // because the value is treated as single object // #2 For members: ordinal ValueMembers are used and they will handle references when appropriate if (Helpers.IsEnum(Type)) { Debug.Assert(IsSimpleValue); IProtoTypeSerializer ser = new WireTypeDecorator(WireType.Variant, new EnumSerializer(Type, GetEnumMap())); if (isRoot && !GetRootStartsGroup()) { ser = new RootFieldNumberDecorator(ser, ListHelpers.FieldItem); } return(ser); } Type itemType = _settingsValueFinal.Member.Collection.ItemType; if (itemType != null) { if (_surrogate != null) { throw new ArgumentException("Repeated data (a list, collection, etc) has inbuilt behaviour and cannot use a surrogate"); } Type defaultType = null; ResolveListTypes(_model, Type, ref itemType, ref defaultType); if (_fields.Count != 0) { throw new ArgumentException("Repeated data (an array, list, etc) has inbuilt behavior and can't have fields"); } // apply default member settings to type settings too var s = _settingsValueFinal.Member; // but change this: s.EffectiveType = Type; // not merged with anything so assign s.Collection.ConcreteType = _settingsValueFinal.ConstructType ?? defaultType; s.Collection.Append = false; // allowed only on members s.WriteAsDynamicType = false; // allowed only on members // this should be handled as collection if (s.Collection.ItemType == null) { s.Collection.ItemType = itemType; } var vs = _rootNestedVs.Clone(); vs.SetSettings(s, 0); vs.DefaultLevel = new ValueSerializationSettings.LevelValue(s.MakeDefaultNestedLevel()); WireType wt; var ser = (IProtoTypeSerializer)_model.ValueSerializerBuilder.BuildValueFinalSerializer(vs, false, out wt); // standard root decorator won't start any field // in compatibility mode collections won't start subitems like normally // so wrap with field if (isRoot && !GetRootStartsGroup()) { ser = new RootFieldNumberDecorator(ser, TypeModel.EnumRootTag); } return(ser); } if (BaseType != null && !BaseType.GetFinalSettingsCopy().IgnoreListHandling&& RuntimeTypeModel.CheckTypeIsCollection(_model, BaseType.Type)) { throw new ArgumentException("A subclass of a repeated data (an array, list, etc should be handled too as a collection"); } // #2 if (_surrogate != null) { MetaType mt = _model[_surrogate], mtBase; while ((mtBase = mt.BaseType) != null) { mt = mtBase; } return(new SurrogateSerializer(_model, Type, _surrogate, mt.Serializer)); } if (_settingsValueFinal.IsAutoTuple) { if (_tupleCtor == null) { throw new InvalidOperationException("Can't find tuple constructor"); } return(new TupleSerializer(_model, _tupleCtor, _tupleFields.ToArray(), _settingsValueFinal.PrefixLength.GetValueOrDefault(true))); } var fields = new BasicList(_fields.Cast <object>()); fields.Trim(); int fieldCount = fields.Count; int subTypeCount = _subTypes?.Count ?? 0; int[] fieldNumbers = new int[fieldCount + subTypeCount]; IProtoSerializerWithWireType[] serializers = new IProtoSerializerWithWireType[fieldCount + subTypeCount]; int i = 0; if (subTypeCount != 0) { Debug.Assert(_subTypes != null, "_subTypes != null"); foreach (SubType subType in _subTypes) { #if WINRT if (!subType.DerivedType.IgnoreListHandling && ienumerable.IsAssignableFrom(subType.DerivedType.Type.GetTypeInfo())) #else if (!subType.DerivedType.IgnoreListHandling && _model.MapType(ienumerable).IsAssignableFrom(subType.DerivedType.Type)) #endif { throw new ArgumentException("Repeated data (a list, collection, etc) has inbuilt behaviour and cannot be used as a subclass"); } fieldNumbers[i] = subType.FieldNumber; serializers[i++] = subType.GetSerializer(_model); } } if (fieldCount != 0) { foreach (ValueMember member in fields) { fieldNumbers[i] = member.FieldNumber; serializers[i++] = member.Serializer; } } BasicList baseCtorCallbacks = null; MetaType tmp = BaseType; while (tmp != null) { MethodInfo method = tmp.HasCallbacks ? tmp.Callbacks.BeforeDeserialize : null; if (method != null) { if (baseCtorCallbacks == null) { baseCtorCallbacks = new BasicList(); } baseCtorCallbacks.Add(method); } tmp = tmp.BaseType; } MethodInfo[] arr = null; if (baseCtorCallbacks != null) { arr = new MethodInfo[baseCtorCallbacks.Count]; baseCtorCallbacks.CopyTo(arr, 0); Array.Reverse(arr); } // root serializer should be always from base type Debug.Assert(!OmitTypeSearchForRootSerialization); if (isRoot && BaseType != null) { return(new ForbiddenRootStub(Type)); } return(new TypeSerializer(_model, Type, fieldNumbers, serializers, arr, BaseType == null, !_settingsValueFinal.SkipConstructor, _callbacks, _settingsValueFinal.ConstructType, _factory, _settingsValueFinal.PrefixLength.Value)); }
internal static Type GetListItemType(TypeModel model, Type listType) { Helpers.DebugAssert(listType != null); #if WINRT TypeInfo listTypeInfo = listType.GetTypeInfo(); if (listType == typeof(string) || listType.IsArray || !typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(listTypeInfo)) { return(null); } #else if (listType == model.MapType(typeof(string)) || listType.IsArray || !model.MapType(typeof(IEnumerable)).IsAssignableFrom(listType)) { return(null); } #endif BasicList candidates = new BasicList(); #if WINRT foreach (MethodInfo method in listType.GetRuntimeMethods()) #else foreach (MethodInfo method in listType.GetMethods()) #endif { if (method.IsStatic || method.Name != "Add") { continue; } ParameterInfo[] parameters = method.GetParameters(); Type paramType; if (parameters.Length == 1 && !candidates.Contains(paramType = parameters[0].ParameterType)) { candidates.Add(paramType); } } string name = listType.Name; bool isQueueStack = name != null && (name.IndexOf("Queue", System.StringComparison.Ordinal) >= 0 || name.IndexOf("Stack", System.StringComparison.Ordinal) >= 0); #if !NO_GENERICS if (!isQueueStack) { TestEnumerableListPatterns(model, candidates, listType); #if WINRT foreach (Type iType in listTypeInfo.ImplementedInterfaces) { TestEnumerableListPatterns(model, candidates, iType); } #else foreach (Type iType in listType.GetInterfaces()) { TestEnumerableListPatterns(model, candidates, iType); } #endif } #endif #if WINRT // more convenient GetProperty overload not supported on all platforms foreach (PropertyInfo indexer in listType.GetRuntimeProperties()) { if (indexer.Name != "Item" || candidates.Contains(indexer.PropertyType)) { continue; } ParameterInfo[] args = indexer.GetIndexParameters(); if (args.Length != 1 || args[0].ParameterType != typeof(int)) { continue; } MethodInfo getter = indexer.GetMethod; if (getter == null || getter.IsStatic) { continue; } candidates.Add(indexer.PropertyType); } #else // more convenient GetProperty overload not supported on all platforms foreach (PropertyInfo indexer in listType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { if (indexer.Name != "Item" || candidates.Contains(indexer.PropertyType)) { continue; } ParameterInfo[] args = indexer.GetIndexParameters(); if (args.Length != 1 || args[0].ParameterType != model.MapType(typeof(int))) { continue; } candidates.Add(indexer.PropertyType); } #endif switch (candidates.Count) { case 0: return(null); case 1: return((Type)candidates[0]); case 2: if (CheckDictionaryAccessors(model, (Type)candidates[0], (Type)candidates[1])) { return((Type)candidates[0]); } if (CheckDictionaryAccessors(model, (Type)candidates[1], (Type)candidates[0])) { return((Type)candidates[1]); } break; } return(null); }
private bool TryDeserializeList(TypeModel model, ProtoReader reader, BinaryDataFormat format, int tag, Type listType, Type itemType, bool isRoot, ref object value) { bool isList; MethodInfo addMethod = TypeModel.ResolveListAdd(model, listType, itemType, out isList); if (addMethod == null) { throw new NotSupportedException("Unknown list variant: " + listType.FullName); } bool found = false; object nextItem = null; IList list = value as IList; object[] args = isList ? null : new object[1]; BasicList arraySurrogate = listType.IsArray ? new BasicList() : null; while (TryDeserializeAuxiliaryType(reader, format, tag, itemType, ref nextItem, true, true, true, true, isRoot)) { found = true; if (value == null && arraySurrogate == null) { value = CreateListInstance(listType, itemType); if (value != null) { ProtoReader.NoteObject(value, reader); } list = value as IList; } if (list != null) { list.Add(nextItem); } else if (arraySurrogate != null) { arraySurrogate.Add(nextItem); } else { args[0] = nextItem; addMethod.Invoke(value, args); } nextItem = null; } if (arraySurrogate != null) { Array newArray; if (value != null) { if (arraySurrogate.Count == 0) { // we'll stay with what we had, thanks } else { Array existing = (Array)value; newArray = Array.CreateInstance(itemType, existing.Length + arraySurrogate.Count); Array.Copy(existing, newArray, existing.Length); arraySurrogate.CopyTo(newArray, existing.Length); value = newArray; } } else { newArray = Array.CreateInstance(itemType, arraySurrogate.Count); arraySurrogate.CopyTo(newArray, 0); value = newArray; ProtoReader.NoteObject(value, reader); } } return(found); }
private void CascadeDependents(BasicList list, MetaType metaType) { MetaType tmp; metaType.FinalizeSettingsValue(); if (metaType.IsList) { Type itemType = TypeModel.GetListItemType(this, metaType.Type); WireType defaultWireType; IProtoSerializer coreSerializer = this.ValueSerializerBuilder.TryGetSimpleCoreSerializer(BinaryDataFormat.Default, itemType, out defaultWireType); if (coreSerializer == null) { int index = FindOrAddAuto(itemType, false, false, false); if (index >= 0) { tmp = ((MetaType)_types[index]).GetSurrogateOrBaseOrSelf(false); if (!list.Contains(tmp)) { // could perhaps also implement as a queue, but this should work OK for sane models list.Add(tmp); CascadeDependents(list, tmp); } } } } else { if (metaType.GetFinalSettingsCopy().IsAutoTuple) { MemberInfo[] mapping; if (MetaType.ResolveTupleConstructor(metaType.Type, out mapping) != null) { for (int i = 0; i < mapping.Length; i++) { CscadeDependents_Member(list, (mapping[i] as PropertyInfo)?.PropertyType ?? (mapping[i] as FieldInfo)?.FieldType); } } } else { foreach (ValueMember member in metaType.Fields) { member.Serializer.GetHashCode(); var s = member.GetFinalSettingsCopy(0); Type type = s.Collection.ItemType ?? member.MemberType; var fieldMetaType = FindWithoutAdd(type); if (fieldMetaType != null) { type = fieldMetaType.GetSurrogateOrSelf().Type; } CscadeDependents_Member(list, type); } } if (metaType.HasSubtypes) { foreach (SubType subType in metaType.GetSubtypes()) { tmp = subType.DerivedType.GetSurrogateOrSelf(); // note: exclude base-types! if (!list.Contains(tmp)) { list.Add(tmp); CascadeDependents(list, tmp); } } } tmp = metaType.BaseType; tmp = tmp?.GetSurrogateOrSelf(); // note: already walking base-types; exclude base if (tmp != null && !list.Contains(tmp)) { list.Add(tmp); CascadeDependents(list, tmp); } } }
/// <summary> /// Suggest a .proto definition for the given type /// </summary> /// <param name="type">The type to generate a .proto definition for, or <c>null</c> to generate a .proto that represents the entire model</param> /// <returns>The .proto definition as a string</returns> public override string GetSchema(Type type) { BasicList requiredTypes = new BasicList(); MetaType primaryType = null; bool isInbuiltType = false; if (type == null) { // generate for the entire model for (int i = _serviceTypesCount; i < _types.Count; i++) { MetaType meta = (MetaType)_types[i]; MetaType tmp = meta.GetSurrogateOrBaseOrSelf(false); if (!requiredTypes.Contains(tmp)) { // ^^^ note that the type might have been added as a descendent requiredTypes.Add(tmp); CascadeDependents(requiredTypes, tmp); } } } else { Type tmp = Helpers.GetNullableUnderlyingType(type); if (tmp != null) { type = tmp; } WireType defaultWireType; isInbuiltType = (this.ValueSerializerBuilder.TryGetSimpleCoreSerializer(BinaryDataFormat.Default, type, out defaultWireType) != null); if (!isInbuiltType) { //Agenerate just relative to the supplied type int index = FindOrAddAuto(type, false, false, false); if (index < 0) { throw new ArgumentException("The type specified is not a contract-type", nameof(type)); } // get the required types primaryType = ((MetaType)_types[index]).GetSurrogateOrBaseOrSelf(false); requiredTypes.Add(primaryType); CascadeDependents(requiredTypes, primaryType); } } // use the provided type's namespace for the "package" StringBuilder headerBuilder = new StringBuilder(); string package = null; if (!isInbuiltType) { IEnumerable typesForNamespace = primaryType == null ? (IEnumerable)MetaTypes : requiredTypes; foreach (MetaType meta in typesForNamespace) { meta.FinalizeSettingsValue(); if (meta.IsList) { continue; } string tmp = meta.Type.Namespace; if (!Helpers.IsNullOrEmpty(tmp)) { if (tmp.StartsWith("System.", StringComparison.Ordinal)) { continue; } if (package == null) { // haven't seen any suggestions yet package = tmp; } else if (package == tmp) { // that's fine; a repeat of the one we already saw } else { // something else; have confliucting suggestions; abort package = null; break; } } } } if (!Helpers.IsNullOrEmpty(package)) { headerBuilder.Append("package ").Append(package).Append(';'); Helpers.AppendLine(headerBuilder); } bool requiresBclImport = false; StringBuilder bodyBuilder = new StringBuilder(); // sort them by schema-name MetaType[] metaTypesArr = new MetaType[requiredTypes.Count]; requiredTypes.CopyTo(metaTypesArr, 0); Array.Sort(metaTypesArr, MetaType.Comparer.Default); // write the messages if (isInbuiltType) { Helpers.AppendLine(bodyBuilder).Append("message ").Append(type.Name).Append(" {"); MetaType.NewLine(bodyBuilder, 1).Append("optional ").Append(GetSchemaTypeName(type, BinaryDataFormat.Default, false, false, ref requiresBclImport)) .Append(" value = 1;"); Helpers.AppendLine(bodyBuilder).Append('}'); } else { for (int i = 0; i < metaTypesArr.Length; i++) { MetaType tmp = metaTypesArr[i]; if (tmp.IsList && tmp != primaryType) { continue; } tmp.WriteSchema(bodyBuilder, 0, ref requiresBclImport); } } if (requiresBclImport) { headerBuilder.Append("import \"bcl.proto\"; // schema for protobuf-net's handling of core .NET types"); Helpers.AppendLine(headerBuilder); } return(Helpers.AppendLine(headerBuilder.Append(bodyBuilder)).ToString()); }
private void WriteGetKeyImpl(TypeBuilder type, bool hasInheritance, SerializerPair[] methodPairs, Compiler.CompilerContext.ILVersion ilVersion, string assemblyName, out ILGenerator il, out int knownTypesCategory, out FieldBuilder knownTypes, out Type knownTypesLookupType) { var genInfo = Override(type, "GetKeyImpl"); il = genInfo.GetILGenerator(); Compiler.CompilerContext ctx = new Compiler.CompilerContext(genInfo, false, false, methodPairs, this, ilVersion, assemblyName, MapType(typeof(System.Type), true)); if (_types.Count <= KnownTypes_ArrayCutoff) { knownTypesCategory = KnownTypes_Array; knownTypesLookupType = MapType(typeof(System.Type[]), true); } else { #if NO_GENERICS knownTypesLookupType = null; #else knownTypesLookupType = MapType(typeof(System.Collections.Generic.Dictionary <System.Type, int>), false); #endif if (knownTypesLookupType == null) { knownTypesLookupType = MapType(typeof(Hashtable), true); knownTypesCategory = KnownTypes_Hashtable; } else { knownTypesCategory = KnownTypes_Dictionary; } } knownTypes = type.DefineField("knownTypes", knownTypesLookupType, FieldAttributes.Private | FieldAttributes.InitOnly | FieldAttributes.Static); switch (knownTypesCategory) { case KnownTypes_Array: { il.Emit(OpCodes.Ldsfld, knownTypes); il.Emit(OpCodes.Ldarg_1); // note that Array.IndexOf is not supported under CF il.EmitCall(OpCodes.Callvirt, MapType(typeof(IList)).GetMethod( "IndexOf", new Type[] { MapType(typeof(object)) }), null); if (hasInheritance) { il.DeclareLocal(MapType(typeof(int))); // loc-0 il.Emit(OpCodes.Dup); il.Emit(OpCodes.Stloc_0); BasicList getKeyLabels = new BasicList(); int lastKey = -1; for (int i = 0; i < methodPairs.Length; i++) { if (methodPairs[i].MetaKey == methodPairs[i].BaseKey) { break; } if (lastKey == methodPairs[i].BaseKey) { // add the last label again getKeyLabels.Add(getKeyLabels[getKeyLabels.Count - 1]); } else { // add a new unique label getKeyLabels.Add(ctx.DefineLabel()); lastKey = methodPairs[i].BaseKey; } } Compiler.CodeLabel[] subtypeLabels = new Compiler.CodeLabel[getKeyLabels.Count]; getKeyLabels.CopyTo(subtypeLabels, 0); ctx.Switch(subtypeLabels); il.Emit(OpCodes.Ldloc_0); // not a sub-type; use the original value il.Emit(OpCodes.Ret); lastKey = -1; // now output the different branches per sub-type (not derived type) for (int i = subtypeLabels.Length - 1; i >= 0; i--) { if (lastKey != methodPairs[i].BaseKey) { lastKey = methodPairs[i].BaseKey; // find the actual base-index for this base-key (i.e. the index of // the base-type) int keyIndex = -1; for (int j = subtypeLabels.Length; j < methodPairs.Length; j++) { if (methodPairs[j].BaseKey == lastKey && methodPairs[j].MetaKey == lastKey) { keyIndex = j; break; } } ctx.MarkLabel(subtypeLabels[i]); Compiler.CompilerContext.LoadValue(il, keyIndex); il.Emit(OpCodes.Ret); } } } else { il.Emit(OpCodes.Ret); } } break; case KnownTypes_Dictionary: { LocalBuilder result = il.DeclareLocal(MapType(typeof(int))); Label otherwise = il.DefineLabel(); il.Emit(OpCodes.Ldsfld, knownTypes); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldloca_S, result); il.EmitCall(OpCodes.Callvirt, knownTypesLookupType.GetMethod("TryGetValue", BindingFlags.Instance | BindingFlags.Public), null); il.Emit(OpCodes.Brfalse_S, otherwise); il.Emit(OpCodes.Ldloc_S, result); il.Emit(OpCodes.Ret); il.MarkLabel(otherwise); il.Emit(OpCodes.Ldc_I4_M1); il.Emit(OpCodes.Ret); } break; case KnownTypes_Hashtable: { Label otherwise = il.DefineLabel(); il.Emit(OpCodes.Ldsfld, knownTypes); il.Emit(OpCodes.Ldarg_1); il.EmitCall(OpCodes.Callvirt, knownTypesLookupType.GetProperty("Item").GetGetMethod(), null); il.Emit(OpCodes.Dup); il.Emit(OpCodes.Brfalse_S, otherwise); #if FX11 il.Emit(OpCodes.Unbox, MapType(typeof(int))); il.Emit(OpCodes.Ldobj, MapType(typeof(int))); #else if (ilVersion == Compiler.CompilerContext.ILVersion.Net1) { il.Emit(OpCodes.Unbox, MapType(typeof(int))); il.Emit(OpCodes.Ldobj, MapType(typeof(int))); } else { il.Emit(OpCodes.Unbox_Any, MapType(typeof(int))); } #endif il.Emit(OpCodes.Ret); il.MarkLabel(otherwise); il.Emit(OpCodes.Pop); il.Emit(OpCodes.Ldc_I4_M1); il.Emit(OpCodes.Ret); } break; default: throw new InvalidOperationException(); } }
private void WriteAssemblyAttributes(CompilerOptions options, string assemblyName, AssemblyBuilder asm) { if (!Helpers.IsNullOrEmpty(options.TargetFrameworkName)) { // get [TargetFramework] from mscorlib/equivalent and burn into the new assembly Type versionAttribType = null; try { // this is best-endeavours only versionAttribType = GetType("System.Runtime.Versioning.TargetFrameworkAttribute", MapType(typeof(string)).Assembly); } catch { /* don't stress */ } if (versionAttribType != null) { PropertyInfo[] props; object[] propValues; if (Helpers.IsNullOrEmpty(options.TargetFrameworkDisplayName)) { props = new PropertyInfo[0]; propValues = new object[0]; } else { props = new PropertyInfo[1] { versionAttribType.GetProperty("FrameworkDisplayName") }; propValues = new object[1] { options.TargetFrameworkDisplayName }; } CustomAttributeBuilder builder = new CustomAttributeBuilder( versionAttribType.GetConstructor(new Type[] { MapType(typeof(string)) }), new object[] { options.TargetFrameworkName }, props, propValues); asm.SetCustomAttribute(builder); } } // copy assembly:InternalsVisibleTo Type internalsVisibleToAttribType = null; #if !FX11 try { internalsVisibleToAttribType = MapType(typeof(System.Runtime.CompilerServices.InternalsVisibleToAttribute)); } catch { /* best endeavors only */ } #endif if (internalsVisibleToAttribType != null) { BasicList internalAssemblies = new BasicList(), consideredAssemblies = new BasicList(); foreach (MetaType metaType in _types) { Assembly assembly = metaType.Type.Assembly; if (consideredAssemblies.IndexOfReference(assembly) >= 0) { continue; } consideredAssemblies.Add(assembly); AttributeMap[] assemblyAttribsMap = AttributeMap.Create(this, assembly); for (int i = 0; i < assemblyAttribsMap.Length; i++) { if (assemblyAttribsMap[i].AttributeType != internalsVisibleToAttribType) { continue; } object privelegedAssemblyObj; assemblyAttribsMap[i].TryGet("AssemblyName", out privelegedAssemblyObj); string privelegedAssemblyName = privelegedAssemblyObj as string; if (privelegedAssemblyName == assemblyName || Helpers.IsNullOrEmpty(privelegedAssemblyName)) { continue; // ignore } if (internalAssemblies.IndexOfString(privelegedAssemblyName) >= 0) { continue; // seen it before } internalAssemblies.Add(privelegedAssemblyName); CustomAttributeBuilder builder = new CustomAttributeBuilder( internalsVisibleToAttribType.GetConstructor(new Type[] { MapType(typeof(string)) }), new object[] { privelegedAssemblyName }); asm.SetCustomAttribute(builder); } } } }
/// <summary> /// Adds a known sub-type to the inheritance model /// </summary> public MetaType AddSubType(int fieldNumber, Type derivedType) { if (derivedType == null) { throw new ArgumentNullException(nameof(derivedType)); } if (fieldNumber < 1) { throw new ArgumentOutOfRangeException(nameof(fieldNumber)); } if (Type.IsArray) { throw new ArgumentException("An array has inbuilt behaviour and cannot be subclassed"); } if (derivedType.IsArray) { throw new ArgumentException("An array has inbuilt behaviour and cannot be as used as a subclass"); } #if WINRT if (!CanHaveSubType(_typeInfo)) { #else if (!CanHaveSubType(Type)) { #endif throw new InvalidOperationException("Sub-types can only be added to non-sealed classes"); } if (!IsValidSubType(derivedType)) { throw new ArgumentException(derivedType.Name + " is not a valid sub-type of " + Type.Name, nameof(derivedType)); } if (_subTypesSimple != null && _subTypesSimple.Contains(derivedType)) { return(this); // already exists } if (!IsFieldFree(fieldNumber)) { throw new ArgumentException(string.Format("FieldNumber {0} was already taken in type {1}, can't add sub-type {2}", fieldNumber, Type.Name, derivedType.Name), nameof(fieldNumber)); } if (_subTypesSimple == null) { _subTypesSimple = new BasicList(); } _subTypesSimple.Add(derivedType); MetaType derivedMeta = _model[derivedType]; ThrowIfFrozen(); derivedMeta.ThrowIfFrozen(); SubType subType = new SubType(fieldNumber, derivedMeta); ThrowIfFrozen(); derivedMeta.SetBaseType(this); // includes ThrowIfFrozen if (_subTypes == null) { _subTypes = new BasicList(); } _subTypes.Add(subType); return(this); }
public Group(int first) { this.First = first; this.Items = new BasicList(); }
public static ConstructorInfo ResolveTupleConstructor(Type type, out MemberInfo[] mappedMembers) { mappedMembers = null; if (type == null) { throw new ArgumentNullException(nameof(type)); } #if WINRT TypeInfo typeInfo = type.GetTypeInfo(); if (typeInfo.IsAbstract) { return(null); // as if! } ConstructorInfo[] ctors = Helpers.GetConstructors(typeInfo, false); #else if (type.IsAbstract) { return(null); // as if! } ConstructorInfo[] ctors = Helpers.GetConstructors(type, false); #endif // need to have an interesting constructor to bother even checking this stuff if (ctors.Length == 0 || (ctors.Length == 1 && ctors[0].GetParameters().Length == 0)) { return(null); } MemberInfo[] fieldsPropsUnfiltered = Helpers.GetInstanceFieldsAndProperties(type, true); BasicList memberList = new BasicList(); for (int i = 0; i < fieldsPropsUnfiltered.Length; i++) { PropertyInfo prop = fieldsPropsUnfiltered[i] as PropertyInfo; if (prop != null) { if (!prop.CanRead) { return(null); // no use if can't read } if (prop.CanWrite && Helpers.GetSetMethod(prop, false, false) != null) { return(null); // don't allow a public set (need to allow non-public to handle Mono's KeyValuePair<,>) } memberList.Add(prop); } else { FieldInfo field = fieldsPropsUnfiltered[i] as FieldInfo; if (field != null) { if (!field.IsInitOnly) { return(null); // all public fields must be readonly to be counted a tuple } memberList.Add(field); } } } if (memberList.Count == 0) { return(null); } MemberInfo[] members = new MemberInfo[memberList.Count]; memberList.CopyTo(members, 0); int[] mapping = new int[members.Length]; int found = 0; ConstructorInfo result = null; mappedMembers = new MemberInfo[mapping.Length]; for (int i = 0; i < ctors.Length; i++) { ParameterInfo[] parameters = ctors[i].GetParameters(); if (parameters.Length != members.Length) { continue; } // reset the mappings to test for (int j = 0; j < mapping.Length; j++) { mapping[j] = -1; } for (int j = 0; j < parameters.Length; j++) { for (int k = 0; k < members.Length; k++) { if (string.Compare(parameters[j].Name, members[k].Name, StringComparison.OrdinalIgnoreCase) != 0) { continue; } Type memberType = Helpers.GetMemberType(members[k]); if (memberType != parameters[j].ParameterType) { continue; } mapping[j] = k; } } // did we map all? bool notMapped = false; for (int j = 0; j < mapping.Length; j++) { if (mapping[j] < 0) { notMapped = true; break; } mappedMembers[j] = members[mapping[j]]; } if (notMapped) { continue; } found++; result = ctors[i]; } return(found == 1 ? result : null); }