Esempio n. 1
0
        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
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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);
                    }
                }
            }
        }
Esempio n. 4
0
        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));
        }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        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);
        }
Esempio n. 7
0
        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);
                }
            }
        }
Esempio n. 8
0
        /// <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);
                    }
                }
            }
        }
Esempio n. 11
0
        /// <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);
        }
Esempio n. 12
0
 public Group(int first)
 {
     this.First = first;
     this.Items = new BasicList();
 }
Esempio n. 13
0
        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);
        }