示例#1
0
 /// <summary>
 /// Returns the ValueMember instances associated with this type
 /// </summary>
 public ValueMember[] GetFields()
 {
     ValueMember[] arr = new ValueMember[_fields.Count];
     _fields.CopyTo(arr, 0);
     Array.Sort(arr, ValueMember.Comparer.Default);
     return(arr);
 }
示例#2
0
 /// <summary>
 /// Returns the SubType instances associated with this type
 /// </summary>
 public SubType[] GetSubtypes()
 {
     if (_subTypes == null || _subTypes.Count == 0)
     {
         return(new SubType[0]);
     }
     SubType[] arr = new SubType[_subTypes.Count];
     _subTypes.CopyTo(arr, 0);
     Array.Sort(arr, SubType.Comparer.Default);
     return(arr);
 }
示例#3
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);
        }
示例#4
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();
            }
        }
        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);
        }