示例#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]);
                    }
                }
            }
        }
示例#2
0
        private void ProcessComplexSerializerMembers(TypeReference type, SerializableTypeInfo serializableTypeInfo, string profile = "Default")
        {
            // Process base type (for complex serializers)
            // If it's a closed type and there is a serializer, we'll serialize parent
            SerializableTypeInfo parentSerializableTypeInfo;
            var parentType = ResolveGenericsVisitor.Process(type, type.Resolve().BaseType);

            if (!parentType.ContainsGenericParameter() && (parentSerializableTypeInfo = GenerateSerializer(parentType, false, profile)) != null &&
                parentSerializableTypeInfo.SerializerType != null)
            {
                serializableTypeInfo.ComplexSerializerProcessParentType = true;
            }

            // Process members
            foreach (var serializableItem in ComplexSerializerRegistry.GetSerializableItems(type, true))
            {
                // Check that all closed types have a proper serializer
                if (serializableItem.Attributes.Any(x => x.AttributeType.FullName == "Xenko.Core.DataMemberCustomSerializerAttribute") ||
                    serializableItem.Type.ContainsGenericParameter())
                {
                    continue;
                }

                var resolvedType = serializableItem.Type.Resolve();
                var isInterface  = resolvedType != null && resolvedType.IsInterface;

                try
                {
                    if (GenerateSerializer(serializableItem.Type, profile: profile) == null)
                    {
                        ComplexSerializerRegistry.IgnoreMember(serializableItem.MemberInfo);
                        if (!isInterface)
                        {
                            log.Write(
                                $"Warning: Member {serializableItem.MemberInfo} does not have a valid serializer. Add [DataMemberIgnore], turn the member non-public, or add a [DataContract] to it's type.");
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new InvalidOperationException($"Could not process serialization for member {serializableItem.MemberInfo}", e);
                }
            }
        }
示例#3
0
        private SerializableTypeInfo CreateComplexSerializer(TypeReference type)
        {
            var isLocal = type.Resolve().Module.Assembly == Assembly;

            // Create a fake TypeReference (even though it doesn't really exist yet, but at least ConvertCSharp to get its name will work).
            TypeReference dataSerializerType;
            var           className = ComplexSerializerRegistry.SerializerTypeName(type, false, true);

            if (type.HasGenericParameters)
            {
                className += "`" + type.GenericParameters.Count;
            }
            if (isLocal && type is TypeDefinition)
            {
                dataSerializerType = new TypeDefinition("Xenko.Core.DataSerializers", className,
                                                        TypeAttributes.AnsiClass | TypeAttributes.AutoClass | TypeAttributes.Sealed |
                                                        TypeAttributes.BeforeFieldInit |
                                                        (type.HasGenericParameters ? TypeAttributes.Public : TypeAttributes.NotPublic));

                // TODO: Only if not using Roslyn
                Assembly.MainModule.Types.Add((TypeDefinition)dataSerializerType);
            }
            else
            {
                dataSerializerType = new TypeReference("Xenko.Core.DataSerializers", className, type.Module, type.Scope);
            }

            var mode = DataSerializerGenericMode.None;

            if (type.HasGenericParameters)
            {
                mode = DataSerializerGenericMode.GenericArguments;

                // Clone generic parameters
                foreach (var genericParameter in type.GenericParameters)
                {
                    var newGenericParameter = new GenericParameter(genericParameter.Name, dataSerializerType)
                    {
                        Attributes = genericParameter.Attributes
                    };

                    // Clone type constraints (others will be in Attributes)
                    foreach (var constraint in genericParameter.Constraints)
                    {
                        newGenericParameter.Constraints.Add(constraint);
                    }

                    dataSerializerType.GenericParameters.Add(newGenericParameter);
                }
            }

            if (dataSerializerType is TypeDefinition dataSerializerTypeDefinition)
            {
                // Setup base class
                var resolvedType            = type.Resolve();
                var useClassDataSerializer  = resolvedType.IsClass && !resolvedType.IsValueType && !resolvedType.IsAbstract && !resolvedType.IsInterface && resolvedType.GetEmptyConstructor() != null;
                var classDataSerializerType = Assembly.GetXenkoCoreModule().GetType(useClassDataSerializer ? "Xenko.Core.Serialization.ClassDataSerializer`1" : "Xenko.Core.Serialization.DataSerializer`1");
                var parentType = Assembly.MainModule.ImportReference(classDataSerializerType).MakeGenericType(type.MakeGenericType(dataSerializerType.GenericParameters.ToArray <TypeReference>()));
                //parentType = ResolveGenericsVisitor.Process(serializerType, type.BaseType);
                dataSerializerTypeDefinition.BaseType = parentType;
            }

            var serializableTypeInfo = new SerializableTypeInfo(dataSerializerType, true, mode);

            serializableTypeInfo.Local = type.Resolve().Module.Assembly == Assembly;
            AddSerializableType(type, serializableTypeInfo);

            if (isLocal && type is TypeDefinition)
            {
                ComplexTypes.Add((TypeDefinition)type, serializableTypeInfo);
            }

            serializableTypeInfo.ComplexSerializer = true;

            return(serializableTypeInfo);
        }