Exemplo n.º 1
0
        public void ProcessSerializers(CecilSerializerContext context)
        {
            // Iterate over each static member of type PropertyKey<> or ParameterKey<>
            foreach (var type in context.Assembly.EnumerateTypes())
            {
                foreach (var member in type.Fields)
                {
                    if (!member.IsStatic || member.IsPrivate)
                        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]);
                    }
                }
            }
        }
 public void ProcessSerializers(CecilSerializerContext context)
 {
     foreach (var type in context.Assembly.EnumerateTypes())
     {
         // Force generation of serializers (complex types, etc...)
         // Check complex type definitions
         ProcessType(context, type);
     }
 }
        private void ProcessXenkoEngineAssembly(CecilSerializerContext context)
        {
            var assembly = context.Assembly;

            // Check "#if IL" directly in the source to easily see what is generated
            GenerateUpdateEngineHelperCode(assembly);
            GenerateUpdatableFieldCode(assembly);
            new UpdatablePropertyCodeGenerator(assembly).GenerateUpdatablePropertyCode();
            new UpdatableListCodeGenerator(assembly).GenerateUpdatablePropertyCode();
        }
        public ComplexSerializerCodeGenerator(IAssemblyResolver assemblyResolver, AssemblyDefinition assembly, ILogger log)
        {
            this.assembly = assembly;
            this.assemblySerializerFactoryClassName = assembly.Name.Name.Replace(" ", string.Empty).Replace(".", string.Empty) + "SerializerFactory";

            // Register referenced assemblies serializer factory, so that we can call them recursively
            foreach (var referencedAssemblyName in assembly.MainModule.AssemblyReferences)
            {
                try
                {
                    var referencedAssembly = assembly.MainModule.AssemblyResolver.Resolve(referencedAssemblyName);

                    var assemblySerializerFactoryType = GetSerializerFactoryType(referencedAssembly);
                    if (assemblySerializerFactoryType != null)
                        referencedAssemblySerializerFactoryTypes.Add(assemblySerializerFactoryType);
                }
                catch (AssemblyResolutionException)
                {
                    continue;
                }
            }

            // Find target framework and replicate it for serializer assembly.
            var targetFrameworkAttribute = assembly.CustomAttributes
                .FirstOrDefault(x => x.AttributeType.FullName == typeof(TargetFrameworkAttribute).FullName);
            if (targetFrameworkAttribute != null)
            {
                targetFramework = "\"" + (string)targetFrameworkAttribute.ConstructorArguments[0].Value + "\"";
                var frameworkDisplayNameField = targetFrameworkAttribute.Properties.FirstOrDefault(x => x.Name == "FrameworkDisplayName");
                if (frameworkDisplayNameField.Name != null)
                {
                    targetFramework += ", FrameworkDisplayName=\"" + (string)frameworkDisplayNameField.Argument.Value + "\"";
                }
            }

            // Prepare serializer processors
            cecilSerializerContext = new CecilSerializerContext(assembly, log);
            var processors = new List<ICecilSerializerProcessor>();

            // Import list of serializer registered by referenced assemblies
            processors.Add(new ReferencedAssemblySerializerProcessor());

            // Generate serializers for types tagged as serializable
            processors.Add(new CecilComplexClassSerializerProcessor());

            // Generate serializers for PropertyKey and ParameterKey
            processors.Add(new PropertyKeySerializerProcessor());

            // Profile serializers
            processors.Add(new ProfileSerializerProcessor());

            // Apply each processor
            foreach (var processor in processors)
                processor.ProcessSerializers(cecilSerializerContext);
        }
Exemplo n.º 5
0
        public void ProcessSerializers(CecilSerializerContext context)
        {
            foreach (var type in context.Assembly.EnumerateTypes())
            {
                var dataContractAttribute = type.CustomAttributes.FirstOrDefault(x => x.AttributeType.FullName == "SiliconStudio.Core.DataContractAttribute" || x.AttributeType.FullName == "SiliconStudio.Core.DataAliasAttribute");

                // Only process if ctor with 1 argument
                if (dataContractAttribute == null || !dataContractAttribute.HasConstructorArguments || dataContractAttribute.ConstructorArguments.Count != 1)
                    continue;

                var alias = (string)dataContractAttribute.ConstructorArguments[0].Value;

                context.DataContractAliases.Add(alias, type);
            }
        }
        private static void ProcessType(CecilSerializerContext context, TypeDefinition type)
        {
            CecilSerializerContext.SerializableTypeInfo serializableTypeInfo;
            if (!context.SerializableTypes.TryGetSerializableTypeInfo(type, false, out serializableTypeInfo)
                && !context.SerializableTypes.TryGetSerializableTypeInfo(type, true, out serializableTypeInfo))
            {
                context.FindSerializerInfo(type, false);
            }

            if (type.HasNestedTypes)
            {
                foreach (var nestedType in type.NestedTypes)
                {
                    ProcessType(context, nestedType);
                }
            }
        }
Exemplo n.º 7
0
        public void ProcessSerializers(CecilSerializerContext context)
        {
            var defaultProfile = context.SerializableTypes;

            foreach (var profile in context.SerializableTypesProfiles)
            {
                // Skip default profile
                if (profile.Value == defaultProfile)
                    continue;

                defaultProfile.IsFrozen = true;

                // For each profile, try to instantiate all types existing in default profile
                foreach (var type in defaultProfile.SerializableTypes)
                {
                    context.GenerateSerializer(type.Key, false, profile.Key);
                }
            }
        }
Exemplo n.º 8
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)
            {
                // 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)
                {
                    continue;
                }

                var referencedAssembly = context.Assembly.MainModule.AssemblyResolver.Resolve(referencedAssemblyName);
                ProcessDataSerializerGlobalAttributes(context, referencedAssembly, false);
            }

            // Find DataSerializer attribute on assembly and/or types
            foreach (var dataSerializerAttribute in
                     assembly.CustomAttributes.Concat(assembly.MainModule.Types.SelectMany(x => x.CustomAttributes)).Where(
                         x => x.AttributeType.FullName == "SiliconStudio.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.");
                    }
                }

                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);
                }
            }
        }
Exemplo n.º 9
0
 public void ProcessSerializers(CecilSerializerContext context)
 {
     ProcessDataSerializerGlobalAttributes(context, context.Assembly, true);
 }
Exemplo n.º 10
0
        public void ProcessSerializers(CecilSerializerContext context)
        {
            var references = new HashSet<AssemblyDefinition>();
            EnumerateReferences(references, context.Assembly);

            // Only process assemblies depending on Xenko.Engine
            if (!references.Any(x => x.Name.Name == "SiliconStudio.Xenko.Engine"))
            {
                // Make sure Xenko.Engine.Serializers can access everything internally
                var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(context.Assembly);
                var internalsVisibleToAttribute = mscorlibAssembly.MainModule.GetTypeResolved(typeof(InternalsVisibleToAttribute).FullName);
                var serializationAssemblyName = "SiliconStudio.Xenko.Engine.Serializers";

                // Add [InteralsVisibleTo] attribute
                var internalsVisibleToAttributeCtor = context.Assembly.MainModule.ImportReference(internalsVisibleToAttribute.GetConstructors().Single());
                var internalsVisibleAttribute = new CustomAttribute(internalsVisibleToAttributeCtor)
                {
                    ConstructorArguments =
                            {
                                new CustomAttributeArgument(context.Assembly.MainModule.ImportReference(context.Assembly.MainModule.TypeSystem.String), serializationAssemblyName)
                            }
                };
                context.Assembly.CustomAttributes.Add(internalsVisibleAttribute);

                return;
            }

            // Get or create method
            var updateEngineType = GetOrCreateUpdateType(context.Assembly, true);
            var mainPrepareMethod = new MethodDefinition("UpdateMain", MethodAttributes.HideBySig | MethodAttributes.Assembly | MethodAttributes.Static, context.Assembly.MainModule.TypeSystem.Void);
            updateEngineType.Methods.Add(mainPrepareMethod);

            // Get some useful Cecil objects from SiliconStudio.Core
            var siliconStudioCoreAssembly = context.Assembly.Name.Name == "SiliconStudio.Core"
                    ? context.Assembly
                    : context.Assembly.MainModule.AssemblyResolver.Resolve("SiliconStudio.Core");
            var siliconStudioCoreModule = siliconStudioCoreAssembly.MainModule;

            var siliconStudioXenkoEngineAssembly = context.Assembly.Name.Name == "SiliconStudio.Xenko.Engine"
                    ? context.Assembly
                    : context.Assembly.MainModule.AssemblyResolver.Resolve("SiliconStudio.Xenko.Engine");
            var siliconStudioXenkoEngineModule = siliconStudioXenkoEngineAssembly.MainModule;

            // Generate IL for SiliconStudio.Core
            if (context.Assembly.Name.Name == "SiliconStudio.Xenko.Engine")
            {
                ProcessXenkoEngineAssembly(context);
            }
            else
            {
#if true || SILICONSTUDIO_XENKO_XAMARIN_CALLI_BUG
                // We still process UpdatableProperty<T> since we had to revert it back when writing back Xenko.Engine (otherwise it crashes at AOT on iOS)
                new UpdatablePropertyCodeGenerator(siliconStudioXenkoEngineAssembly).GenerateUpdatablePropertyCode();
#endif
            }

            animationDataType = siliconStudioXenkoEngineModule.GetType("SiliconStudio.Xenko.Animations.AnimationData`1");

            var updatableFieldGenericType = siliconStudioXenkoEngineModule.GetType("SiliconStudio.Xenko.Updater.UpdatableField`1");
            updatableFieldGenericCtor = updatableFieldGenericType.Methods.First(x => x.IsConstructor && !x.IsStatic);

            updatablePropertyGenericType = siliconStudioXenkoEngineModule.GetType("SiliconStudio.Xenko.Updater.UpdatableProperty`1");
            updatablePropertyGenericCtor = updatablePropertyGenericType.Methods.First(x => x.IsConstructor && !x.IsStatic);

            var updatablePropertyObjectGenericType = siliconStudioXenkoEngineModule.GetType("SiliconStudio.Xenko.Updater.UpdatablePropertyObject`1");
            updatablePropertyObjectGenericCtor = updatablePropertyObjectGenericType.Methods.First(x => x.IsConstructor && !x.IsStatic);

            var updatableListUpdateResolverGenericType = siliconStudioXenkoEngineModule.GetType("SiliconStudio.Xenko.Updater.ListUpdateResolver`1");
            updatableListUpdateResolverGenericCtor = updatableListUpdateResolverGenericType.Methods.First(x => x.IsConstructor && !x.IsStatic);

            var updatableArrayUpdateResolverGenericType = siliconStudioXenkoEngineModule.GetType("SiliconStudio.Xenko.Updater.ArrayUpdateResolver`1");
            updatableArrayUpdateResolverGenericCtor = updatableArrayUpdateResolverGenericType.Methods.First(x => x.IsConstructor && !x.IsStatic);

            updateEngineRegisterMemberMethod = context.Assembly.MainModule.ImportReference(siliconStudioXenkoEngineModule.GetType("SiliconStudio.Xenko.Updater.UpdateEngine").Methods.First(x => x.Name == "RegisterMember"));
            updateEngineRegisterMemberResolverMethod = context.Assembly.MainModule.ImportReference(siliconStudioXenkoEngineModule.GetType("SiliconStudio.Xenko.Updater.UpdateEngine").Methods.First(x => x.Name == "RegisterMemberResolver"));

            var typeType = CecilExtensions.FindCorlibAssembly(context.Assembly).MainModule.GetTypeResolved(typeof(Type).FullName);
            getTypeFromHandleMethod = context.Assembly.MainModule.ImportReference(typeType.Methods.First(x => x.Name == "GetTypeFromHandle"));

            // Make sure it is called at module startup
            var moduleInitializerAttribute = siliconStudioCoreModule.GetType("SiliconStudio.Core.ModuleInitializerAttribute");
            mainPrepareMethod.CustomAttributes.Add(new CustomAttribute(context.Assembly.MainModule.ImportReference(moduleInitializerAttribute.GetConstructors().Single(x => !x.IsStatic))));

            // Emit serialization code for all the types we care about
            foreach (var serializableType in context.SerializableTypesProfiles.SelectMany(x => x.Value.SerializableTypes))
            {
                // Special case: when processing Xenko.Engine assembly, we automatically add dependent assemblies types too
                if (!serializableType.Value.Local && siliconStudioXenkoEngineAssembly != context.Assembly)
                    continue;

                var typeDefinition = serializableType.Key as TypeDefinition;
                if (typeDefinition == null)
                    continue;

                try
                {
                    ProcessType(context, typeDefinition, mainPrepareMethod);
                }
                catch (Exception e)
                {
                    throw new InvalidOperationException(string.Format("Error when generating update engine code for {0}", typeDefinition), e);
                }
            }

            // Force generic instantiations
            var il = mainPrepareMethod.Body.GetILProcessor();
            foreach (var serializableType in context.SerializableTypesProfiles.SelectMany(x => x.Value.SerializableTypes).ToArray())
            {
                // Special case: when processing Xenko.Engine assembly, we automatically add dependent assemblies types too
                if (!serializableType.Value.Local && siliconStudioXenkoEngineAssembly != context.Assembly)
                    continue;

                // Make sure AnimationData<T> is serializable
                //if (serializableType.Value.Mode == DataSerializerGenericMode.None)
                //    context.GenerateSerializer(context.Assembly.MainModule.ImportReference(animationDataType).MakeGenericType(context.Assembly.MainModule.ImportReference(serializableType.Key)));

                // Try to find if original method definition was generated
                var typeDefinition = serializableType.Key.Resolve();

                // If using List<T>, register this type in UpdateEngine
                var listInterfaceType = typeDefinition.Interfaces.OfType<GenericInstanceType>().FirstOrDefault(x => x.ElementType.FullName == typeof(IList<>).FullName);
                if (listInterfaceType != null)
                {
                    //call Updater.UpdateEngine.RegisterMemberResolver(new Updater.ListUpdateResolver<T>());
                    var elementType = ResolveGenericsVisitor.Process(serializableType.Key, listInterfaceType.GenericArguments[0]);
                    il.Emit(OpCodes.Newobj, context.Assembly.MainModule.ImportReference(updatableListUpdateResolverGenericCtor).MakeGeneric(context.Assembly.MainModule.ImportReference(elementType).FixupValueType()));
                    il.Emit(OpCodes.Call, updateEngineRegisterMemberResolverMethod);
                }

                // Same for arrays
                var arrayType = serializableType.Key as ArrayType;
                if (arrayType != null)
                {
                    //call Updater.UpdateEngine.RegisterMemberResolver(new Updater.ArrayUpdateResolver<T>());
                    var elementType = ResolveGenericsVisitor.Process(serializableType.Key, arrayType.ElementType);
                    il.Emit(OpCodes.Newobj, context.Assembly.MainModule.ImportReference(updatableArrayUpdateResolverGenericCtor).MakeGeneric(context.Assembly.MainModule.ImportReference(elementType).FixupValueType()));
                    il.Emit(OpCodes.Call, updateEngineRegisterMemberResolverMethod);
                }

                var genericInstanceType = serializableType.Key as GenericInstanceType;
                if (genericInstanceType == null)
                {
                    var updateMethod = GetOrCreateUpdateType(typeDefinition.Module.Assembly, false)?.Methods.FirstOrDefault(x => x.Name == ComputeUpdateMethodName(typeDefinition));

                    // If nothing was found in main assembly, also look in SiliconStudio.Xenko.Engine assembly, just in case (it might defines some shared/corlib types -- currently not the case)
                    if (updateMethod == null)
                    {
                        updateMethod = GetOrCreateUpdateType(siliconStudioXenkoEngineAssembly, false)?.Methods.FirstOrDefault(x => x.Name == ComputeUpdateMethodName(typeDefinition));
                    }

                    if (updateMethod != null)
                    {
                        // Emit call to update engine setup method with generic arguments of current type
                        il.Emit(OpCodes.Call, context.Assembly.MainModule.ImportReference(updateMethod)
                            .MakeGenericMethod(genericInstanceType.GenericArguments
                                .Select(context.Assembly.MainModule.ImportReference)
                                .Select(CecilExtensions.FixupValueType).ToArray()));
                    }
                }
            }

            il.Emit(OpCodes.Ret);

#if true || SILICONSTUDIO_XENKO_XAMARIN_CALLI_BUG
            // Due to Xamarin iOS AOT limitation, we can't keep this type around because it fails compilation
            if (context.Assembly.Name.Name == "SiliconStudio.Xenko.Engine")
            {
                NotImplementedBody(updatablePropertyGenericType.Methods.First(x => x.Name == "GetStructAndUnbox"));
                NotImplementedBody(updatablePropertyGenericType.Methods.First(x => x.Name == "GetBlittable"));
                NotImplementedBody(updatablePropertyGenericType.Methods.First(x => x.Name == "SetStruct"));
                NotImplementedBody(updatablePropertyGenericType.Methods.First(x => x.Name == "SetBlittable"));
            }
#endif
        }
Exemplo n.º 11
0
        public void ProcessType(CecilSerializerContext context, TypeReference type, MethodDefinition updateMainMethod)
        {
            var typeDefinition = type.Resolve();

            // No need to process enum
            if (typeDefinition.IsEnum)
                return;

            var updateCurrentMethod = updateMainMethod;
            ResolveGenericsVisitor replaceGenericsVisitor = null;

            if (typeDefinition.HasGenericParameters)
            {
                // Make a prepare method for just this object since it might need multiple instantiation
                updateCurrentMethod = new MethodDefinition(ComputeUpdateMethodName(typeDefinition), MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, context.Assembly.MainModule.TypeSystem.Void);
                var genericsMapping = new Dictionary<TypeReference, TypeReference>();
                foreach (var genericParameter in typeDefinition.GenericParameters)
                {
                    var genericParameterCopy = new GenericParameter(genericParameter.Name, updateCurrentMethod)
                    {
                        Attributes = genericParameter.Attributes,
                    };
                    foreach (var constraint in genericParameter.Constraints)
                        genericParameterCopy.Constraints.Add(context.Assembly.MainModule.ImportReference(constraint));
                    updateCurrentMethod.GenericParameters.Add(genericParameterCopy);

                    genericsMapping[genericParameter] = genericParameterCopy;
                }

                replaceGenericsVisitor = new ResolveGenericsVisitor(genericsMapping);

                updateMainMethod.DeclaringType.Methods.Add(updateCurrentMethod);
            }

            var il = updateCurrentMethod.Body.GetILProcessor();
            var emptyObjectField = updateMainMethod.DeclaringType.Fields.FirstOrDefault(x => x.Name == "emptyObject");

            // Note: forcing fields and properties to be processed in all cases
            foreach (var serializableItem in ComplexClassSerializerGenerator.GetSerializableItems(type, true, ComplexTypeSerializerFlags.SerializePublicFields | ComplexTypeSerializerFlags.SerializePublicProperties | ComplexTypeSerializerFlags.Updatable))
            {
                var fieldReference = serializableItem.MemberInfo as FieldReference;
                if (fieldReference != null)
                {
                    var field = fieldReference.Resolve();

                    // First time it is needed, let's create empty object: var emptyObject = new object();
                    if (emptyObjectField == null)
                    {
                        emptyObjectField = new FieldDefinition("emptyObject", FieldAttributes.Static | FieldAttributes.Private, context.Assembly.MainModule.TypeSystem.Object);

                        // Create static ctor that will initialize this object
                        var staticConstructor = new MethodDefinition(".cctor",
                                                MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                                                context.Assembly.MainModule.TypeSystem.Void);
                        var staticConstructorIL = staticConstructor.Body.GetILProcessor();
                        staticConstructorIL.Emit(OpCodes.Newobj, context.Assembly.MainModule.ImportReference(emptyObjectField.FieldType.Resolve().GetConstructors().Single(x => !x.IsStatic && !x.HasParameters)));
                        staticConstructorIL.Emit(OpCodes.Stsfld, emptyObjectField);
                        staticConstructorIL.Emit(OpCodes.Ret);

                        updateMainMethod.DeclaringType.Fields.Add(emptyObjectField);
                        updateMainMethod.DeclaringType.Methods.Add(staticConstructor);
                    }

                    il.Emit(OpCodes.Ldtoken, type);
                    il.Emit(OpCodes.Call, getTypeFromHandleMethod);
                    il.Emit(OpCodes.Ldstr, field.Name);

                    il.Emit(OpCodes.Ldsfld, emptyObjectField);
                    il.Emit(OpCodes.Ldflda, context.Assembly.MainModule.ImportReference(fieldReference));
                    il.Emit(OpCodes.Ldsfld, emptyObjectField);
                    il.Emit(OpCodes.Conv_I);
                    il.Emit(OpCodes.Sub);
                    il.Emit(OpCodes.Conv_I4);

                    var fieldType = context.Assembly.MainModule.ImportReference(replaceGenericsVisitor != null ? replaceGenericsVisitor.VisitDynamic(field.FieldType) : field.FieldType).FixupValueType();
                    il.Emit(OpCodes.Newobj, context.Assembly.MainModule.ImportReference(updatableFieldGenericCtor).MakeGeneric(fieldType));
                    il.Emit(OpCodes.Call, updateEngineRegisterMemberMethod);
                }

                var propertyReference = serializableItem.MemberInfo as PropertyReference;
                if (propertyReference != null)
                {
                    var property = propertyReference.Resolve();

                    var propertyGetMethod = context.Assembly.MainModule.ImportReference(property.GetMethod).MakeGeneric(updateCurrentMethod.GenericParameters.ToArray());

                    il.Emit(OpCodes.Ldtoken, type);
                    il.Emit(OpCodes.Call, getTypeFromHandleMethod);
                    il.Emit(OpCodes.Ldstr, property.Name);

                    il.Emit(OpCodes.Ldftn, propertyGetMethod);

                    // Only get setter if it exists and it's public
                    if (property.SetMethod != null && property.SetMethod.IsPublic)
                    {
                        var propertySetMethod = context.Assembly.MainModule.ImportReference(property.SetMethod).MakeGeneric(updateCurrentMethod.GenericParameters.ToArray());
                        il.Emit(OpCodes.Ldftn, propertySetMethod);
                    }
                    else
                    {
                        // 0 (native int)
                        il.Emit(OpCodes.Ldc_I4_0);
                        il.Emit(OpCodes.Conv_I);
                    }

                    var propertyType = context.Assembly.MainModule.ImportReference(replaceGenericsVisitor != null ? replaceGenericsVisitor.VisitDynamic(property.PropertyType) : property.PropertyType).FixupValueType();

                    var updatablePropertyInflatedCtor = GetOrCreateUpdatablePropertyCtor(context.Assembly, propertyType);

                    il.Emit(OpCodes.Newobj, updatablePropertyInflatedCtor);
                    il.Emit(OpCodes.Call, updateEngineRegisterMemberMethod);
                }
            }

            if (updateCurrentMethod != updateMainMethod)
            {
                // If we have a local method, close it
                il.Emit(OpCodes.Ret);

                // Also call it from main method if it was a closed generic instantiation
                if (type is GenericInstanceType)
                {
                    il = updateMainMethod.Body.GetILProcessor();
                    il.Emit(OpCodes.Call, updateCurrentMethod.MakeGeneric(((GenericInstanceType)type).GenericArguments.Select(context.Assembly.MainModule.ImportReference).Select(CecilExtensions.FixupValueType).ToArray()));
                }
            }
        }
        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.Types.SelectMany(x => x.CustomAttributes)).Where(
                    x => x.AttributeType.FullName == "SiliconStudio.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.");
                }

                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);
 }