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); }
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); } } }
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); } } }
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); } } }
public void ProcessSerializers(CecilSerializerContext context) { ProcessDataSerializerGlobalAttributes(context, context.Assembly, true); }
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 }
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); } } }