Esempio n. 1
0
        public void ProcessSerializers(CecilSerializerContext context)
        {
            // Iterate over each static member of type PropertyKey<> or ParameterKey<>
            foreach (var type in context.Assembly.MainModule.GetAllTypes())
            {
                foreach (var member in type.Fields)
                {
                    if (!member.IsStatic || !member.IsPublic)
                    {
                        continue;
                    }

                    if (ComplexSerializerRegistry.IsMemberIgnored(member.CustomAttributes, ComplexTypeSerializerFlags.SerializePublicFields, DataMemberMode.Default))
                    {
                        continue;
                    }

                    if (member.FieldType.Name == "PropertyKey`1" ||
                        member.FieldType.Name == "ParameterKey`1" ||
                        member.FieldType.Name == "ValueParameterKey`1" ||
                        member.FieldType.Name == "ObjectParameterKey`1" ||
                        member.FieldType.Name == "PermutationParameterKey`1")
                    {
                        context.GenerateSerializer(member.FieldType);

                        var genericType = (GenericInstanceType)member.FieldType;

                        // Also generate serializer for embedded type
                        context.GenerateSerializer(genericType.GenericArguments[0]);
                    }
                }
            }
        }
        private void ProcessDataSerializerGlobalAttributes(CecilSerializerContext context, AssemblyDefinition assembly, bool local)
        {
            // Already processed?
            if (!processedAssemblies.Add(assembly))
            {
                return;
            }

            // TODO: Add a flag for ComplexSerializer and transmit it properly (it needs different kind of analysis)

            // Let's recurse over referenced assemblies
            foreach (var referencedAssemblyName in assembly.MainModule.AssemblyReferences.ToArray())
            {
                // Avoid processing system assemblies
                // TODO: Scan what is actually in framework folders
                if (referencedAssemblyName.Name == "mscorlib" || referencedAssemblyName.Name.StartsWith("System") ||
                    referencedAssemblyName.FullName.Contains("PublicKeyToken=31bf3856ad364e35") || // Signed with Microsoft public key (likely part of system libraries)
                    referencedAssemblyName.Name.StartsWith("SharpDX"))
                {
                    continue;
                }

                try
                {
                    var referencedAssembly = context.Assembly.MainModule.AssemblyResolver.Resolve(referencedAssemblyName);

                    ProcessDataSerializerGlobalAttributes(context, referencedAssembly, false);
                }
                catch (AssemblyResolutionException)
                {
                    continue;
                }
            }

            // Find DataSerializer attribute on assembly and/or types
            foreach (var dataSerializerAttribute in
                     assembly.CustomAttributes.Concat(assembly.MainModule.GetAllTypes().SelectMany(x => x.CustomAttributes)).Where(
                         x => x.AttributeType.FullName == "Stride.Core.Serialization.DataSerializerGlobalAttribute")
                     .OrderBy(x => x.ConstructorArguments[0].Value != null ? -1 : 1)) // Order so that we first have the ones which don't require us to go through GenerateSerializer
            {
                var dataSerializerType = (TypeReference)dataSerializerAttribute.ConstructorArguments[0].Value;
                var dataType           = (TypeReference)dataSerializerAttribute.ConstructorArguments[1].Value;
                var mode              = (DataSerializerGenericMode)dataSerializerAttribute.ConstructorArguments[2].Value;
                var inherited         = (bool)dataSerializerAttribute.ConstructorArguments[3].Value;
                var complexSerializer = (bool)dataSerializerAttribute.ConstructorArguments[4].Value;
                var profile           = dataSerializerAttribute.Properties.Where(x => x.Name == "Profile").Select(x => (string)x.Argument.Value).FirstOrDefault() ?? "Default";

                if (dataType == null)
                {
                    if (mode == DataSerializerGenericMode.None)
                    {
                        dataType = FindSerializerDataType(dataSerializerType);
                    }
                    else
                    {
                        throw new InvalidOperationException("Can't deduce data serializer type for generic types.");
                    }
                }

                // Reading from custom arguments doesn't have its ValueType properly set
                dataType           = dataType.FixupValueType();
                dataSerializerType = dataSerializerType?.FixupValueType();

                CecilSerializerContext.SerializableTypeInfo serializableTypeInfo;

                if (dataSerializerType == null)
                {
                    // TODO: We should avoid calling GenerateSerializer now just to have the dataSerializerType (we should do so only in a second step)
                    serializableTypeInfo = context.GenerateSerializer(dataType, profile: profile);
                    if (serializableTypeInfo == null)
                    {
                        throw new InvalidOperationException(string.Format("Can't find serializer for type {0}", dataType));
                    }
                    serializableTypeInfo.IsLocal         = local;
                    serializableTypeInfo.IsExistingLocal = local;
                    dataSerializerType = serializableTypeInfo.SerializerType;
                }
                else
                {
                    // Add it to list of serializable types
                    serializableTypeInfo = new CecilSerializerContext.SerializableTypeInfo(dataSerializerType, local, mode)
                    {
                        IsExistingLocal = local, IsInherited = inherited, IsComplexSerializer = complexSerializer
                    };
                    context.AddSerializableType(dataType, serializableTypeInfo, profile);
                }
            }
        }