コード例 #1
0
 private void AddNestedTypes(TypeDefinition type, GenericInstanceTypeMap genericInstanceTypeMap)
 {
     foreach (TypeDefinition nestedType in type.NestedTypes)
     {
         AddType(nestedType, genericInstanceTypeMap);
     }
 }
コード例 #2
0
        private FieldInfo[] GetFields(TypeDefinition type, bool isGenericInstance, GenericInstanceTypeMap genericInstanceTypeMap)
        {
            var fields = new List <FieldInfo>();

            foreach (FieldDefinition field in type.Fields)
            {
                var fieldInfo = GetFieldInfo(type, field, isGenericInstance, genericInstanceTypeMap);

                if (fieldInfo != null)
                {
                    fields.Add(fieldInfo.Value);
                }
            }

            return(fields.ToArray());
        }
コード例 #3
0
        private void AddBaseType(TypeReference typeRef, GenericInstanceTypeMap genericInstanceTypeMap)
        {
            var baseType = typeRef.Resolve().BaseType;

            if (baseType != null)
            {
                /* If we are processing generic instance type and
                 * its base type happens to be a generic instance class as well,
                 * we want to forward our generic arguments to the base. Consider:
                 *
                 *  class One<T>
                 *  {
                 *      T one;
                 *  }
                 *
                 *  class Two<T1, T2> : One<T2>
                 *  {
                 *  }
                 *
                 *  class Three : Two<int, float>
                 *  {
                 *  }
                 *
                 * In this case, three is inheriting from Two<int, float>,
                 * so we want Two<int, float> to inherit from One<float>,
                 * however, cecil will tell us that base of Two<T1, T2> is One<T2>,
                 * therefore we have to create the generic instance type of One<float> ourselves
                 */
                if (typeRef.IsGenericInstance && baseType.IsGenericInstance)
                {
                    var genericInstance = ((GenericInstanceType)baseType);
                    baseType = MakeGenericInstance(genericInstance.ElementType, genericInstance.GenericArguments, genericInstanceTypeMap);
                }

                AddType(baseType, genericInstanceTypeMap);
            }
        }
コード例 #4
0
        private FieldInfo?GetFieldInfo(TypeDefinition type, FieldDefinition field, bool isDeclaringTypeGenericInstance,
                                       GenericInstanceTypeMap genericInstanceTypeMap)
        {
            if (!WillSerialize(field))
            {
                return(null);
            }

            var ti = new FieldInfo();

            ti.name = field.Name;

            TypeReference fieldType;

            if (isDeclaringTypeGenericInstance)
            {
                fieldType = ResolveGenericInstanceType(field.FieldType, genericInstanceTypeMap);
            }
            else
            {
                fieldType = field.FieldType;
            }

            ti.type  = GetMonoEmbeddedFullTypeNameFor(fieldType);
            ti.flags = FieldInfoFlags.None;

            var fixedBufferAttribute = GetFixedBufferAttribute(field);

            if (fixedBufferAttribute != null)
            {
                ti.flags              |= FieldInfoFlags.FixedBuffer;
                ti.fixedBufferLength   = GetFixedBufferLength(fixedBufferAttribute);
                ti.fixedBufferTypename = GetFixedBufferTypename(fixedBufferAttribute);
            }
            return(ti);
        }
コード例 #5
0
        private TypeReference MakeGenericInstance(TypeReference genericClass, IEnumerable <TypeReference> arguments, GenericInstanceTypeMap genericInstanceTypeMap)
        {
            var genericInstance = new GenericInstanceType(genericClass);

            foreach (var argument in arguments.Select(x => ResolveGenericInstanceType(x, genericInstanceTypeMap)))
            {
                genericInstance.GenericArguments.Add(argument);
            }

            return(genericInstance);
        }
コード例 #6
0
        private void AddType(TypeReference typeRef, GenericInstanceTypeMap genericInstanceTypeMap)
        {
            // Prevent duplicates
            if (classes_.Any(x => x.name == GetMonoEmbeddedFullTypeNameFor(typeRef)))
            {
                return;
            }

            TypeDefinition type;

            try
            {
                type = typeRef.Resolve();
            } // This will happen for types which we don't have access to, like Windows.Foundation.IAsyncOperation<int>
            catch (AssemblyResolutionException)
            {
                return;
            }
            catch (NotSupportedException) // "NotSupportedException: Version not supported: 255.255.255.255" is thrown when assembly references WinRT assembly (e.g. mscorlib)
            {
                return;
            }

            if (type == null)
            {
                return;
            }

            if (typeRef.IsGenericInstance)
            {
                var arguments  = ((GenericInstanceType)typeRef).GenericArguments;
                var parameters = type.GenericParameters;

                for (int i = 0; i < arguments.Count; i++)
                {
                    if (parameters[i] != arguments[i])
                    {
                        genericInstanceTypeMap[parameters[i]] = arguments[i];
                    }
                }

                typeResolver.Add((GenericInstanceType)typeRef);
            }

            /* Process class itself before nested/base types in case user does something evil, for example:
             *
             *  class Outer
             *  {
             *      class Inner : Child
             *      {
             *      }
             *  }
             *
             *  class Child : Outer
             *  {
             *  }
             */

            bool shouldImplementDeserializable = false;

            try
            {
                shouldImplementDeserializable = UnitySerializationLogic.ShouldImplementIDeserializable(type);
            }
            catch
            {
                // If assembly has unknown reference (for ex., see tests VariousPlugins, where Metro plugins are used), skip field
            }

            if (!shouldImplementDeserializable)
            {
                // In this case we only take care of processing the nested types, if any.
                AddNestedTypes(type, genericInstanceTypeMap);
            }
            else
            {
                var ci = new ClassInfo();
                ci.name   = GetMonoEmbeddedFullTypeNameFor(typeRef);
                ci.fields = GetFields(type, typeRef.IsGenericInstance, genericInstanceTypeMap);

                classes_.Add(ci);

                // Fetch info for inner types
                AddNestedTypes(type, genericInstanceTypeMap);

                // Add base type
                AddBaseType(typeRef, genericInstanceTypeMap);
            }

            if (typeRef.IsGenericInstance)
            {
                typeResolver.Remove((GenericInstanceType)typeRef);
            }
        }
コード例 #7
0
        /* We use this GenericInstanceTypeMap to map generic types to their generic instance types,
         * This is needed for correctly assess inheritance in cases like this:
         *
         *  class One<T>
         *  {
         *      public T one;
         *  }
         *
         *  class Two : One<int>
         *  {
         *  }
         *
         * In this case, we look at type Two, and see that it inherits from type One<int>,
         * so we map T -> int. When we come across looking at field "one", we see that its
         * declaring type is a generic instance type and that T maps to int, so it writes down
         * that class One<int> has a field "int one".
         *
         * We use a new map for going through each type instance (check GatherClassInfo()).
         */
        private TypeReference ResolveGenericInstanceType(TypeReference typeToResolve, GenericInstanceTypeMap genericInstanceTypeMap)
        {
            var arrayType = typeToResolve as ArrayType;

            if (arrayType != null)
            {
                typeToResolve = new ArrayType(ResolveGenericInstanceType(arrayType.ElementType, genericInstanceTypeMap), arrayType.Rank);
            }

            while (genericInstanceTypeMap.ContainsKey(typeToResolve))
            {
                typeToResolve = genericInstanceTypeMap[typeToResolve];
            }

            if (typeToResolve.IsGenericInstance)
            {
                // Handle the case of nested generics, like List<Dictionary<int, List<string>>>
                var genericInstance = ((GenericInstanceType)typeToResolve);
                typeToResolve = MakeGenericInstance(genericInstance.ElementType, genericInstance.GenericArguments, genericInstanceTypeMap);
            }

            return(typeToResolve);
        }