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 == "Xenko.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.Local         = local;
                    serializableTypeInfo.ExistingLocal = local;
                    dataSerializerType = serializableTypeInfo.SerializerType;
                }
                else
                {
                    // Add it to list of serializable types
                    serializableTypeInfo = new CecilSerializerContext.SerializableTypeInfo(dataSerializerType, local, mode)
                    {
                        ExistingLocal = local, Inherited = inherited, ComplexSerializer = complexSerializer
                    };
                    context.AddSerializableType(dataType, serializableTypeInfo, profile);
                }
            }
        }
 public void ProcessSerializers(CecilSerializerContext context)
 {
     ProcessDataSerializerGlobalAttributes(context, context.Assembly, true);
 }