コード例 #1
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 ComplexClassSerializerGenerator.GetSerializableItems(type, true))
            {
                var resolvedType = serializableItem.Type.Resolve();
                // Check that all closed types have a proper serializer
                if (serializableItem.Attributes.Any(x => x.AttributeType.FullName == "SiliconStudio.Core.DataMemberCustomSerializerAttribute") ||
                    (resolvedType != null && resolvedType.IsInterface) ||
                    serializableItem.Type.ContainsGenericParameter())
                {
                    continue;
                }

                if (GenerateSerializer(serializableItem.Type, profile: profile) == null)
                {
                    throw new InvalidOperationException(string.Format("Member {0} (type: {1}) doesn't seem to have a valid serializer.", serializableItem.MemberInfo, serializableItem.Type.ConvertCSharp()));
                }
            }
        }
コード例 #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 ComplexClassSerializerGenerator.GetSerializableItems(type, true))
            {
                var resolvedType = serializableItem.Type.Resolve();
                // Check that all closed types have a proper serializer
                if (serializableItem.Attributes.Any(x => x.AttributeType.FullName == "SiliconStudio.Core.DataMemberCustomSerializerAttribute") ||
                    (resolvedType != null && resolvedType.IsInterface) ||
                    serializableItem.Type.ContainsGenericParameter())
                {
                    continue;
                }

                if (GenerateSerializer(serializableItem.Type, profile: profile) == null)
                {
                    ComplexClassSerializerGenerator.IgnoreMember(serializableItem.MemberInfo);
                    log.Log(new LogMessage(log.Module, LogMessageType.Warning, string.Format("Member {0} does not have a valid serializer. Add [DataMemberIgnore], turn the member non-public, or add a [DataContract] to it's type.", serializableItem.MemberInfo)));
                }
            }
        }
コード例 #3
0
        private static void UpdateType(Type type, HashSet <Type> checkedTypes)
        {
            if (checkedTypes.Contains(type))
            {
                return;
            }

            checkedTypes.Add(type);
            SerializableTypeInfo typeInfo = CheckSerializableTypeInfo(type);

            SerializableTypeCache[type] = typeInfo;

            if (typeInfo == null)
            {
                if (typeof(IList).IsAssignableFrom(type))
                {
                    Type elementType = GetListElementType(type);

                    if (elementType != null)
                    {
                        UpdateType(elementType, checkedTypes);
                    }

                    return;
                }

                if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(System.Nullable <>))
                {
                    UpdateType(type.GetGenericArguments()[0], checkedTypes);
                    return;
                }

                foreach (var info in type.GetFields())
                {
                    if (!info.IsStatic)
                    {
                        if (info.HasAttribute <Nullable>())
                        {
                            NullableParamCache.Add(info);
                        }

                        UpdateType(info.FieldType, checkedTypes);
                    }
                }

                foreach (var info in type.GetProperties())
                {
                    if (info.CanRead && info.CanWrite)
                    {
                        if (info.HasAttribute <Nullable>())
                        {
                            NullableParamCache.Add(info);
                        }

                        UpdateType(info.PropertyType, checkedTypes);
                    }
                }
            }
        }
コード例 #4
0
 void ISerializableTypeVisitor.VisitSerializableClass(SerializableTypeInfo serializableTypeInfo)
 {
     if (serializableTypeInfo.Type == null || serializableTypeInfo.Type.IsConcreteType())
     {
         _serializers.Add(new DefaultSerializer(serializableTypeInfo));
         _deserializers.Add(new DefaultDeserializer(serializableTypeInfo));
     }
 }
コード例 #5
0
        public void AcceptOnType(ISerializableTypeVisitor visitor)
        {
            var typeInfo = new SerializableTypeInfo(Type, PackformatName, Version, SerializableMemberCandidates);

            if (HasDataContractAttribute)
            {
                CheckIfTypeHasProperDataContractAttirbuteInHierarchy();
                visitor.VisitSerializableClass(typeInfo);
            }
        }
コード例 #6
0
 public void AddSerializableTypeInfo(TypeReference typeReference, SerializableTypeInfo serializableTypeInfo)
 {
     if (serializableTypeInfo.Mode != DataSerializerGenericMode.None)
     {
         GenericSerializableTypes.Add(typeReference, serializableTypeInfo);
     }
     else
     {
         SerializableTypes.Add(typeReference, serializableTypeInfo);
     }
 }
コード例 #7
0
 public void AddSerializableTypeInfo(TypeReference typeReference, SerializableTypeInfo serializableTypeInfo)
 {
     if (serializableTypeInfo.Mode != DataSerializerGenericMode.None)
     {
         GenericSerializableTypes.Add(typeReference, serializableTypeInfo);
     }
     else
     {
         if (IsFrozen)
         {
             throw new InvalidOperationException(string.Format("Unexpected type [{0}] to add while serializable types are frozen", typeReference));
         }
         SerializableTypes.Add(typeReference, serializableTypeInfo);
     }
 }
コード例 #8
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);
                }
            }
        }
コード例 #9
0
        private SerializableTypeInfo CreateComplexSerializer(TypeReference type)
        {
            // Create a fake TypeReference (even though it doesn't really exist yet, but at least ConvertCSharp to get its name will work).
            var dataSerializerType = new TypeReference("SiliconStudio.DataSerializers",
                                                       ComplexClassSerializerGenerator.SerializerTypeName(type, false, true), 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);
                }
            }

            var isLocal = type.Resolve().Module.Assembly == Assembly;
            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);
        }
コード例 #10
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);
        }
コード例 #11
0
        /// <summary>
        /// Ensure the following type can be serialized. If not, try to register appropriate serializer.
        /// This method can be recursive.
        /// </summary>
        /// <param name="type">The type.</param>
        public SerializableTypeInfo GenerateSerializer(TypeReference type, bool force = true, string profile = "Default", bool generic = false)
        {
            var serializableTypes = GetSerializableTypes(profile);

            // Already handled?
            SerializableTypeInfo serializableTypeInfo;
            if (serializableTypes.TryGetSerializableTypeInfo(type, generic, out serializableTypeInfo))
                return serializableTypeInfo;

            // Try to get one without generic
            if (generic && serializableTypes.TryGetSerializableTypeInfo(type, false, out serializableTypeInfo))
                return serializableTypeInfo;

            // TDOO: Array, List, Generic types, etc... (equivalent of previous serializer factories)
            var arrayType = type as ArrayType;
            if (arrayType != null)
            {
                // Only proceed if element type is serializable (and in Default profile, otherwise ElementType is enough)
                if (GenerateSerializer(arrayType.ElementType, force, profile) != null)
                {
                    if (profile == "Default")
                    {
                        var arraySerializerType = SiliconStudioCoreAssembly.MainModule.GetTypeResolved("SiliconStudio.Core.Serialization.Serializers.ArraySerializer`1");
                        var serializerType = new GenericInstanceType(arraySerializerType);
                        serializerType.GenericArguments.Add(arrayType.ElementType);
                        AddSerializableType(type, serializableTypeInfo = new SerializableTypeInfo(serializerType, true), profile);
                        return serializableTypeInfo;
                    }
                    else
                    {
                        // Fallback to default
                        return GenerateSerializer(type, force, "Default");
                    }
                }

                return null;
            }

            // Try to match with existing generic serializer (for List, Dictionary, etc...)
            var genericInstanceType = type as GenericInstanceType;
            if (genericInstanceType != null)
            {
                var elementType = genericInstanceType.ElementType;
                SerializableTypeInfo elementSerializableTypeInfo;
                if ((elementSerializableTypeInfo = GenerateSerializer(elementType, false, profile, true)) != null)
                {
                    switch (elementSerializableTypeInfo.Mode)
                    {
                        case DataSerializerGenericMode.Type:
                        {
                            var serializerType = new GenericInstanceType(elementSerializableTypeInfo.SerializerType);
                            serializerType.GenericArguments.Add(type);

                            AddSerializableType(type, serializableTypeInfo = new SerializableTypeInfo(serializerType, true) { ComplexSerializer = elementSerializableTypeInfo.ComplexSerializer }, profile);
                            break;
                        }
                        case DataSerializerGenericMode.TypeAndGenericArguments:
                        {
                            var serializerType = new GenericInstanceType(elementSerializableTypeInfo.SerializerType);
                            serializerType.GenericArguments.Add(type);
                            foreach (var genericArgument in genericInstanceType.GenericArguments)
                            {
                                // Generate serializer for each generic argument
                                //GenerateSerializer(genericArgument);
            
                                serializerType.GenericArguments.Add(genericArgument);
                            }

                            AddSerializableType(type, serializableTypeInfo = new SerializableTypeInfo(serializerType, true) { ComplexSerializer = elementSerializableTypeInfo.ComplexSerializer }, profile);
                            break;
                        }
                        case DataSerializerGenericMode.GenericArguments:
                        {
                            var serializerType = new GenericInstanceType(elementSerializableTypeInfo.SerializerType);
                            foreach (var genericArgument in genericInstanceType.GenericArguments)
                            {
                                // Generate serializer for each generic argument
                                //GenerateSerializer(genericArgument);
            
                                serializerType.GenericArguments.Add(genericArgument);
                            }

                            AddSerializableType(type, serializableTypeInfo = new SerializableTypeInfo(serializerType, true) { ComplexSerializer = elementSerializableTypeInfo.ComplexSerializer }, profile);
                            break;
                        }
                        default:
                            throw new NotImplementedException();
                    }
            
                    if (elementSerializableTypeInfo.ComplexSerializer)
                    {
                        ProcessComplexSerializerMembers(type, serializableTypeInfo);
                    }
                    return serializableTypeInfo;
                }
            }

            // Check complex type definitions
            if (profile == "Default" && (serializableTypeInfo = FindSerializerInfo(type, generic)) != null)
            {
                return serializableTypeInfo;
            }

            // Fallback to default
            if (profile != "Default")
                return GenerateSerializer(type, force, "Default", generic);

            // Part after that is only if a serializer is absolutely necessary. This is skipped when scanning normal assemblies type that might have nothing to do with serialization.
            if (!force)
                return null;
            
            // Non instantiable type? (object, interfaces, abstract classes)
            // Serializer can be null since they will be inherited anyway (handled through MemberSerializer)
            var resolvedType = type.Resolve();
            if (resolvedType.IsAbstract || resolvedType.IsInterface || resolvedType.FullName == typeof(object).FullName)
            {
                AddSerializableType(type, serializableTypeInfo = new SerializableTypeInfo(null, true), profile);
                return serializableTypeInfo;
            }

            return null;
        }
コード例 #12
0
        /// <summary>
        /// Ensure the following type can be serialized. If not, try to register appropriate serializer.
        /// This method can be recursive.
        /// </summary>
        /// <param name="type">The type.</param>
        public SerializableTypeInfo GenerateSerializer(TypeReference type, bool force = true, string profile = "Default", bool generic = false)
        {
            var serializableTypes = GetSerializableTypes(profile);

            // Already handled?
            SerializableTypeInfo serializableTypeInfo;

            if (serializableTypes.TryGetSerializableTypeInfo(type, generic, out serializableTypeInfo))
            {
                return(serializableTypeInfo);
            }

            // Try to get one without generic
            if (generic && serializableTypes.TryGetSerializableTypeInfo(type, false, out serializableTypeInfo))
            {
                return(serializableTypeInfo);
            }

            // TDOO: Array, List, Generic types, etc... (equivalent of previous serializer factories)
            var arrayType = type as ArrayType;

            if (arrayType != null)
            {
                // Only proceed if element type is serializable (and in Default profile, otherwise ElementType is enough)
                if (GenerateSerializer(arrayType.ElementType, force, profile) != null)
                {
                    if (profile == "Default")
                    {
                        var arraySerializerType = SiliconStudioCoreAssembly.MainModule.GetTypeResolved("SiliconStudio.Core.Serialization.Serializers.ArraySerializer`1");
                        var serializerType      = new GenericInstanceType(arraySerializerType);
                        serializerType.GenericArguments.Add(arrayType.ElementType);
                        AddSerializableType(type, serializableTypeInfo = new SerializableTypeInfo(serializerType, true), profile);
                        return(serializableTypeInfo);
                    }
                    else
                    {
                        // Fallback to default
                        return(GenerateSerializer(type, force, "Default"));
                    }
                }

                return(null);
            }

            // Try to match with existing generic serializer (for List, Dictionary, etc...)
            var genericInstanceType = type as GenericInstanceType;

            if (genericInstanceType != null)
            {
                var elementType = genericInstanceType.ElementType;
                SerializableTypeInfo elementSerializableTypeInfo;
                if ((elementSerializableTypeInfo = GenerateSerializer(elementType, false, profile, true)) != null)
                {
                    switch (elementSerializableTypeInfo.Mode)
                    {
                    case DataSerializerGenericMode.Type:
                    {
                        var serializerType = new GenericInstanceType(elementSerializableTypeInfo.SerializerType);
                        serializerType.GenericArguments.Add(type);

                        AddSerializableType(type, serializableTypeInfo = new SerializableTypeInfo(serializerType, true)
                            {
                                ComplexSerializer = elementSerializableTypeInfo.ComplexSerializer
                            }, profile);
                        break;
                    }

                    case DataSerializerGenericMode.TypeAndGenericArguments:
                    {
                        var serializerType = new GenericInstanceType(elementSerializableTypeInfo.SerializerType);
                        serializerType.GenericArguments.Add(type);
                        foreach (var genericArgument in genericInstanceType.GenericArguments)
                        {
                            // Generate serializer for each generic argument
                            //GenerateSerializer(genericArgument);

                            serializerType.GenericArguments.Add(genericArgument);
                        }

                        AddSerializableType(type, serializableTypeInfo = new SerializableTypeInfo(serializerType, true)
                            {
                                ComplexSerializer = elementSerializableTypeInfo.ComplexSerializer
                            }, profile);
                        break;
                    }

                    case DataSerializerGenericMode.GenericArguments:
                    {
                        var serializerType = new GenericInstanceType(elementSerializableTypeInfo.SerializerType);
                        foreach (var genericArgument in genericInstanceType.GenericArguments)
                        {
                            // Generate serializer for each generic argument
                            //GenerateSerializer(genericArgument);

                            serializerType.GenericArguments.Add(genericArgument);
                        }

                        AddSerializableType(type, serializableTypeInfo = new SerializableTypeInfo(serializerType, true)
                            {
                                ComplexSerializer = elementSerializableTypeInfo.ComplexSerializer
                            }, profile);
                        break;
                    }

                    default:
                        throw new NotImplementedException();
                    }

                    if (elementSerializableTypeInfo.ComplexSerializer)
                    {
                        ProcessComplexSerializerMembers(type, serializableTypeInfo);
                    }
                    return(serializableTypeInfo);
                }
            }

            // Check complex type definitions
            if (profile == "Default" && (serializableTypeInfo = FindSerializerInfo(type, generic)) != null)
            {
                return(serializableTypeInfo);
            }

            // Fallback to default
            if (profile != "Default")
            {
                return(GenerateSerializer(type, force, "Default", generic));
            }

            // Part after that is only if a serializer is absolutely necessary. This is skipped when scanning normal assemblies type that might have nothing to do with serialization.
            if (!force)
            {
                return(null);
            }

            // Non instantiable type? (object, interfaces, abstract classes)
            // Serializer can be null since they will be inherited anyway (handled through MemberSerializer)
            var resolvedType = type.Resolve();

            if (resolvedType.IsAbstract || resolvedType.IsInterface || resolvedType.FullName == typeof(object).FullName)
            {
                AddSerializableType(type, serializableTypeInfo = new SerializableTypeInfo(null, true), profile);
                return(serializableTypeInfo);
            }

            return(null);
        }
コード例 #13
0
 public bool TryGetSerializableTypeInfo(TypeReference type, bool generic, out SerializableTypeInfo result)
 {
     return(generic
         ? GenericSerializableTypes.TryGetValue(type, out result)
         : SerializableTypes.TryGetValue(type, out result));
 }
コード例 #14
0
        /// <summary>
        /// Finds the serializer information.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="generic">If set to true, when using <see cref="DataSerializerGenericMode.Type"/>, it will returns the generic version instead of actual type one.</param>
        /// <returns></returns>
        /// <exception cref="System.InvalidOperationException">Not sure how to process this inherited serializer</exception>
        internal SerializableTypeInfo FindSerializerInfo(TypeReference type, bool generic)
        {
            if (type == null || type.FullName == typeof(object).FullName || type.FullName == typeof(ValueType).FullName || type.IsGenericParameter)
                return null;

            var resolvedType = type.Resolve();

            // Nested type
            if (resolvedType.IsNested)
            {
                // Check public/private flags
                if (!resolvedType.IsNestedPublic && !resolvedType.IsNestedAssembly)
                    return null;
            }

            if (resolvedType.IsEnum)
            {
                // Enum
                // Let's generate a EnumSerializer
                var enumSerializerType = SiliconStudioCoreAssembly.MainModule.GetTypeResolved("SiliconStudio.Core.Serialization.Serializers.EnumSerializer`1");
                var serializerType = new GenericInstanceType(enumSerializerType);
                serializerType.GenericArguments.Add(type);

                var serializableTypeInfo = new SerializableTypeInfo(serializerType, true, DataSerializerGenericMode.None);
                AddSerializableType(type, serializableTypeInfo);
                return serializableTypeInfo;
            }

            // 1. Check if there is a Serializable attribute
            // Note: Not anymore since we don't want all system types to have unknown complex serializers.
            //if (((resolvedType.Attributes & TypeAttributes.Serializable) == TypeAttributes.Serializable) || resolvedType.CustomAttributes.Any(x => x.AttributeType.FullName == typeof(SerializableAttribute).FullName))
            //{
            //    serializerInfo.Serializable = true;
            //    serializerInfo.ComplexSerializer = true;
            //    serializerInfo.ComplexSerializerName = SerializerTypeName(resolvedType);
            //    return serializerInfo;
            //}

            // 2.1. Check if there is DataSerializerAttribute on this type (if yes, it is serializable, but not a "complex type")
            var dataSerializerAttribute =
                resolvedType.CustomAttributes.FirstOrDefault(
                    x => x.AttributeType.FullName == "SiliconStudio.Core.Serialization.DataSerializerAttribute");
            if (dataSerializerAttribute != null)
            {
                var modeField = dataSerializerAttribute.Fields.FirstOrDefault(x => x.Name == "Mode");
                var mode = (modeField.Name != null) ? (DataSerializerGenericMode)modeField.Argument.Value : DataSerializerGenericMode.None;

                // TODO: Replace with ResolveGenericsVisitor
                var dataSerializerType = ((TypeReference)dataSerializerAttribute.ConstructorArguments[0].Value);
                if (mode == DataSerializerGenericMode.Type || (mode == DataSerializerGenericMode.TypeAndGenericArguments && type is GenericInstanceType))
                {
                    var genericSerializableTypeInfo = new SerializableTypeInfo(dataSerializerType, true, mode) { Inherited = true };
                    AddSerializableType(type, genericSerializableTypeInfo);

                    var actualSerializerType = new GenericInstanceType(dataSerializerType);

                    // Add Type as generic arguments
                    actualSerializerType.GenericArguments.Add(type);

                    // If necessary, add generic arguments too
                    if (mode == DataSerializerGenericMode.TypeAndGenericArguments)
                    {
                        foreach (var genericArgument in ((GenericInstanceType)type).GenericArguments)
                        {
                            actualSerializerType.GenericArguments.Add(genericArgument);
                        }
                    }

                    // Special case for GenericMode == DataSerializerGenericMode.Type: we store actual serializer instantiation in SerializerType (alongside the generic version in GenericSerializerType).
                    var serializableTypeInfo = new SerializableTypeInfo(actualSerializerType, true);
                    AddSerializableType(type, serializableTypeInfo);

                    if (!generic)
                        return serializableTypeInfo;

                    return genericSerializableTypeInfo;
                }
                else
                {
                    var serializableTypeInfo = new SerializableTypeInfo(dataSerializerType, true, mode) { Inherited = false };
                    AddSerializableType(type, serializableTypeInfo);
                    return serializableTypeInfo;
                }
            }

            // 2.2. Check if SerializableExtendedAttribute is set on this class, or any of its base class with ApplyHierarchy
            var serializableExtendedAttribute =
                resolvedType.CustomAttributes.FirstOrDefault(
                    x => x.AttributeType.FullName == "SiliconStudio.Core.DataContractAttribute");
            if (dataSerializerAttribute == null && serializableExtendedAttribute != null)
            {
                // CHeck if ApplyHierarchy is active, otherwise it needs to be the exact type.
                var inherited = serializableExtendedAttribute.Properties.Where(x => x.Name == "Inherited")
                    .Select(x => (bool)x.Argument.Value)
                    .FirstOrDefault();

                var serializableTypeInfo = CreateComplexSerializer(type);
                serializableTypeInfo.Inherited = inherited;

                // Process members
                ProcessComplexSerializerMembers(type, serializableTypeInfo);

                return serializableTypeInfo;
            }

            // Check if parent type contains Inherited attribute
            var parentType = ResolveGenericsVisitor.Process(type, type.Resolve().BaseType);
            if (parentType != null)
            {
                // Generate serializer for parent type
                var parentSerializableInfoType = GenerateSerializer(parentType.Resolve(), false, generic: true);

                // If Inherited flag is on, we also generate a serializer for this type
                if (parentSerializableInfoType != null && parentSerializableInfoType.Inherited)
                {
                    if (parentSerializableInfoType.ComplexSerializer)
                    {
                        var serializableTypeInfo = CreateComplexSerializer(type);
                        serializableTypeInfo.Inherited = true;

                        // Process members
                        ProcessComplexSerializerMembers(type, serializableTypeInfo);

                        return serializableTypeInfo;
                    }
                    else if (parentSerializableInfoType.Mode == DataSerializerGenericMode.Type || parentSerializableInfoType.Mode == DataSerializerGenericMode.TypeAndGenericArguments)
                    {
                        // Register generic version
                        var genericSerializableTypeInfo = new SerializableTypeInfo(parentSerializableInfoType.SerializerType, true, parentSerializableInfoType.Mode);
                        AddSerializableType(type, genericSerializableTypeInfo);

                        if (!type.HasGenericParameters)
                        {
                            var actualSerializerType = new GenericInstanceType(parentSerializableInfoType.SerializerType);

                            // Add Type as generic arguments
                            actualSerializerType.GenericArguments.Add(type);

                            // If necessary, add generic arguments too
                            if (parentSerializableInfoType.Mode == DataSerializerGenericMode.TypeAndGenericArguments)
                            {
                                foreach (var genericArgument in ((GenericInstanceType)parentType).GenericArguments)
                                {
                                    actualSerializerType.GenericArguments.Add(genericArgument);
                                }
                            }

                            // Register actual type
                            var serializableTypeInfo = new SerializableTypeInfo(actualSerializerType, true);
                            AddSerializableType(type, serializableTypeInfo);

                            if (!generic)
                                return serializableTypeInfo;
                        }

                        return genericSerializableTypeInfo;
                    }
                    else
                    {
                        throw new InvalidOperationException("Not sure how to process this inherited serializer");
                    }
                }
            }

            return null;
        }
コード例 #15
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 ComplexClassSerializerGenerator.GetSerializableItems(type, true))
            {
                // Check that all closed types have a proper serializer
                if (serializableItem.Attributes.Any(x => x.AttributeType.FullName == "SiliconStudio.Core.DataMemberCustomSerializerAttribute")
                    || serializableItem.Type.ContainsGenericParameter())
                    continue;

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

                if (GenerateSerializer(serializableItem.Type, profile: profile) == null)
                {
                    ComplexClassSerializerGenerator.IgnoreMember(serializableItem.MemberInfo);
                    if (!isInterface)
                        log.Log(new LogMessage(log.Module, LogMessageType.Warning, string.Format("Member {0} does not have a valid serializer. Add [DataMemberIgnore], turn the member non-public, or add a [DataContract] to it's type.", serializableItem.MemberInfo)));
                }
            }
        }
コード例 #16
0
 public DefaultDeserializer(SerializableTypeInfo serializableTypeInfo)
     : base(serializableTypeInfo.PackformatName, serializableTypeInfo.Version)
 {
     _serializableTypeInfo = serializableTypeInfo;
     _packItemCandidates   = serializableTypeInfo.Items.ToDictionary(item => item.Name);
 }
コード例 #17
0
        public static void Serialize <T>(BinaryWriter writer, Type type, bool nullable, T value)
        {
            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(System.Nullable <>))
            {
                Type underlyingType = type.GetGenericArguments()[0];
                Serialize(writer, underlyingType, true, value);
                return;
            }

            if (nullable)
            {
                if (value == null)
                {
                    writer.Write((byte)0);
                    return;
                }

                writer.Write((byte)1);
            }
            else if (value == null)
            {
                throw new SerializationException("Trying to serialize a non Nullable null value");
            }

            Action <BinaryWriter, object, bool> serializerFunc;

            if (WriteFunctions.TryGetValue(type, out serializerFunc))
            {
                serializerFunc(writer, value, nullable);
                return;
            }

            if (type.IsEnum)
            {
                Type underlyingType = Enum.GetUnderlyingType(type);

                if (WriteFunctions.TryGetValue(underlyingType, out serializerFunc))
                {
                    serializerFunc(writer, Convert.ChangeType(value, underlyingType), nullable);
                }
                else
                {
                    throw new SerializationException("Enum " + type.Name + " underlying type is not serializable.");
                }

                return;
            }

            SerializableTypeInfo serTypeInfo = SerializableTypeCache[type];

            if (serTypeInfo != null)
            {
                if (serTypeInfo.SerializeMethod.IsStatic)
                {
                    serTypeInfo.SerializeMethod.Invoke(null, new object[] { value, writer });
                }
                else
                {
                    serTypeInfo.SerializeMethod.Invoke(value, new object[] { writer });
                }

                return;
            }

            Type elementType = GetListElementType(type);

            if (elementType != null)
            {
                Action <BinaryWriter, object, bool> writeFunc = (wrtr, vlue, nlble) => {
                    wrtr.Write(checked ((ushort)((ICollection)vlue).Count));

                    foreach (var el in (IEnumerable)vlue)
                    {
                        Serialize(wrtr, elementType, nlble, el);
                    }
                };

                WriteFunctions[type] = writeFunc;
                writeFunc(writer, value, nullable);
                return;
            }

            foreach (var info in RpcInterface.GetOrederedFields(type))
            {
                if (!info.IsStatic)
                {
                    Serialize(writer, info.FieldType, NullableParamCache.Contains(info), info.GetValue(value));
                }
            }

            foreach (var info in RpcInterface.GetOrderedProperties(type))
            {
                if (info.CanRead && info.CanWrite)
                {
                    Serialize(writer, info.PropertyType, NullableParamCache.Contains(info), info.GetValue(value, null));
                }
            }
        }
コード例 #18
0
        /// <summary>
        ///   Finds the serializer information.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="isGenericType">
        ///   If set to <c>true</c>, when using <see cref="DataSerializerGenericMode.Type"/>, it will return the generic version
        ///   instead of actual type one.
        /// </param>
        /// <returns>Serializer information for the specified type.</returns>
        /// <exception cref="InvalidOperationException">Not sure how to process this inherited serializer.</exception>
        internal SerializableTypeInfo FindSerializerInfo(TypeReference type, bool isGenericType)
        {
            if (type is null ||
                type.FullName == typeof(object).FullName ||
                type.FullName == typeof(ValueType).FullName ||
                type.IsGenericParameter)
            {
                return(null);
            }

            var resolvedType = type.Resolve();

            // Nested type
            if (resolvedType.IsNested)
            {
                // Check public/private flags
                if (!resolvedType.IsNestedPublic && !resolvedType.IsNestedAssembly)
                {
                    return(null);
                }
            }

            if (resolvedType.IsEnum)
            {
                // Enum
                // Let's generate an EnumSerializer
                var enumSerializerType = StrideCoreModule.GetTypeResolved("Stride.Core.Serialization.Serializers.EnumSerializer`1");
                var serializerType     = new GenericInstanceType(enumSerializerType);
                serializerType.GenericArguments.Add(type);

                var serializableTypeInfo = new SerializableTypeInfo(serializerType, isLocal: true, DataSerializerGenericMode.None);
                AddSerializableType(type, serializableTypeInfo);
                return(serializableTypeInfo);
            }

            // 1. Check if there is DataSerializerAttribute on this type (if yes, it is serializable, but not a "complex type")
            var dataSerializerAttribute = resolvedType.CustomAttributes.FirstOrDefault(
                x => x.AttributeType.FullName == "Stride.Core.Serialization.DataSerializerAttribute");

            if (dataSerializerAttribute != null)
            {
                var modeField = dataSerializerAttribute.Fields.FirstOrDefault(x => x.Name == "Mode");
                var mode      = (modeField.Name != null) ? (DataSerializerGenericMode)modeField.Argument.Value : DataSerializerGenericMode.None;

                var dataSerializerType = (TypeReference)dataSerializerAttribute.ConstructorArguments[0].Value;

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

                if (mode == DataSerializerGenericMode.Type ||
                    (mode == DataSerializerGenericMode.TypeAndGenericArguments && type is GenericInstanceType))
                {
                    var genericSerializableTypeInfo = new SerializableTypeInfo(dataSerializerType, isLocal: true, mode)
                    {
                        IsInherited = true
                    };
                    AddSerializableType(type, genericSerializableTypeInfo);

                    var actualSerializerType = new GenericInstanceType(dataSerializerType);

                    // Add Type as generic arguments
                    actualSerializerType.GenericArguments.Add(type);

                    // If necessary, add generic arguments too
                    if (mode == DataSerializerGenericMode.TypeAndGenericArguments)
                    {
                        foreach (var genericArgument in ((GenericInstanceType)type).GenericArguments)
                        {
                            actualSerializerType.GenericArguments.Add(genericArgument);
                        }
                    }

                    // Special case for GenericMode == DataSerializerGenericMode.Type:
                    //   We store actual serializer instantiation in SerializerType (alongside the generic version in GenericSerializerType)
                    var serializableTypeInfo = new SerializableTypeInfo(actualSerializerType, isLocal: true);
                    AddSerializableType(type, serializableTypeInfo);

                    if (!isGenericType)
                    {
                        return(serializableTypeInfo);
                    }

                    return(genericSerializableTypeInfo);
                }
                else
                {
                    var serializableTypeInfo = new SerializableTypeInfo(dataSerializerType, isLocal: true, mode)
                    {
                        IsInherited = false
                    };
                    AddSerializableType(type, serializableTypeInfo);
                    return(serializableTypeInfo);
                }
            }

            // 2. Check if SerializableExtendedAttribute is set on this class, or any of its base class with ApplyHierarchy
            var serializableExtendedAttribute = resolvedType.CustomAttributes.FirstOrDefault(
                x => x.AttributeType.FullName == "Stride.Core.DataContractAttribute");

            if (dataSerializerAttribute is null && serializableExtendedAttribute != null)
            {
                // CHeck if ApplyHierarchy is active, otherwise it needs to be the exact type
                var inherited = serializableExtendedAttribute.Properties
                                .Where(x => x.Name == "Inherited")
                                .Select(x => (bool)x.Argument.Value)
                                .FirstOrDefault();

                var serializableTypeInfo = CreateComplexSerializer(type);
                serializableTypeInfo.IsInherited = inherited;

                // Process members
                ProcessComplexSerializerMembers(type, serializableTypeInfo);

                return(serializableTypeInfo);
            }

            // Check if parent type contains Inherited attribute
            var parentType = ResolveGenericsVisitor.Process(type, type.Resolve().BaseType);

            if (parentType != null)
            {
                // Generate serializer for parent type
                var parentSerializableInfoType = GenerateSerializer(parentType.Resolve(), force: false, isGenericType: true);

                // If Inherited flag is on, we also generate a serializer for this type
                if (parentSerializableInfoType != null && parentSerializableInfoType.IsInherited)
                {
                    if (parentSerializableInfoType.IsComplexSerializer)
                    {
                        var serializableTypeInfo = CreateComplexSerializer(type);
                        serializableTypeInfo.IsInherited = true;

                        // Process members
                        ProcessComplexSerializerMembers(type, serializableTypeInfo);

                        return(serializableTypeInfo);
                    }
                    else if (parentSerializableInfoType.GenericsMode == DataSerializerGenericMode.Type ||
                             parentSerializableInfoType.GenericsMode == DataSerializerGenericMode.TypeAndGenericArguments)
                    {
                        // Register generic version
                        var genericSerializableTypeInfo = new SerializableTypeInfo(parentSerializableInfoType.SerializerType, isLocal: true, parentSerializableInfoType.GenericsMode);
                        AddSerializableType(type, genericSerializableTypeInfo);

                        if (!type.HasGenericParameters)
                        {
                            var actualSerializerType = new GenericInstanceType(parentSerializableInfoType.SerializerType);

                            // Add Type as generic arguments
                            actualSerializerType.GenericArguments.Add(type);

                            // If necessary, add generic arguments too
                            if (parentSerializableInfoType.GenericsMode == DataSerializerGenericMode.TypeAndGenericArguments)
                            {
                                foreach (var genericArgument in ((GenericInstanceType)parentType).GenericArguments)
                                {
                                    actualSerializerType.GenericArguments.Add(genericArgument);
                                }
                            }

                            // Register actual type
                            var serializableTypeInfo = new SerializableTypeInfo(actualSerializerType, isLocal: true);
                            AddSerializableType(type, serializableTypeInfo);

                            if (!isGenericType)
                            {
                                return(serializableTypeInfo);
                            }
                        }

                        return(genericSerializableTypeInfo);
                    }
                    else
                    {
                        throw new InvalidOperationException("Not sure how to process inherited serializer.");
                    }
                }
            }

            return(null);
        }
コード例 #19
0
        public static object Deserialize(BinaryReader reader, Type type, bool nullable)
        {
            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(System.Nullable <>))
            {
                Type underlyingType = type.GetGenericArguments()[0];
                return(Deserialize(reader, underlyingType, true));
            }

            if (nullable && reader.ReadByte() == 0)
            {
                return(null);
            }

            Func <BinaryReader, bool, object> deserializerFunc;

            if (ReadFunctions.TryGetValue(type, out deserializerFunc))
            {
                return(deserializerFunc(reader, nullable));
            }

            if (type.IsEnum)
            {
                Type underlyingType = Enum.GetUnderlyingType(type);

                if (ReadFunctions.TryGetValue(underlyingType, out deserializerFunc))
                {
                    object value = deserializerFunc(reader, nullable);
                    return(Enum.ToObject(type, value));
                }

                throw new SerializationException("Enum " + type.Name + " underlying type is not serializable.");
            }

            SerializableTypeInfo serTypeInfo = SerializableTypeCache[type];

            if (serTypeInfo != null)
            {
                if (serTypeInfo.DeserializeMethod != null)
                {
                    return(serTypeInfo.DeserializeMethod.Invoke(null, new object[] { reader }));
                }

                if (serTypeInfo.Constructor != null)
                {
                    return(Activator.CreateInstance(type, reader));
                }
            }

            Type elementType = GetListElementType(type);

            if (elementType != null)
            {
                Func <BinaryReader, bool, object> readFunc;

                if (type.IsArray)
                {
                    readFunc = (rdr, nlble) => {
                        int length = rdr.ReadUInt16();
                        var array  = (Array)Activator.CreateInstance(type, length);

                        for (int i = 0; i < length; ++i)
                        {
                            array.SetValue(Deserialize(rdr, elementType, nlble), i);
                        }

                        return(array);
                    };
                }
                else
                {
                    Type listType = typeof(List <>).MakeGenericType(elementType);

                    readFunc = (rdr, nlble) => {
                        int length = rdr.ReadUInt16();
                        var list   = (IList)Activator.CreateInstance(listType);

                        for (int i = 0; i < length; ++i)
                        {
                            list.Add(Deserialize(rdr, elementType, nlble));
                        }

                        return(list);
                    };
                }

                ReadFunctions[type] = readFunc;
                return(readFunc(reader, nullable));
            }

            var obj = Activator.CreateInstance(type);

            foreach (var info in RpcInterface.GetOrederedFields(type))
            {
                if (!info.IsStatic)
                {
                    var fieldValue = Deserialize(reader, info.FieldType, NullableParamCache.Contains(info));
                    info.SetValue(obj, fieldValue);
                }
            }

            foreach (var info in RpcInterface.GetOrderedProperties(type))
            {
                if (info.CanRead && info.CanWrite)
                {
                    var propValue = Deserialize(reader, info.PropertyType, NullableParamCache.Contains(info));
                    info.SetValue(obj, propValue, null);
                }
            }

            return(obj);
        }
コード例 #20
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 ComplexClassSerializerGenerator.GetSerializableItems(type, true))
            {
                var resolvedType = serializableItem.Type.Resolve();
                // Check that all closed types have a proper serializer
                if (serializableItem.Attributes.Any(x => x.AttributeType.FullName == "SiliconStudio.Core.DataMemberCustomSerializerAttribute")
                    || (resolvedType != null && resolvedType.IsInterface)
                    || serializableItem.Type.ContainsGenericParameter())
                    continue;

                if (GenerateSerializer(serializableItem.Type, profile: profile) == null)
                {
                    throw new InvalidOperationException(string.Format("Member {0} (type: {1}) doesn't seem to have a valid serializer.", serializableItem.MemberInfo, serializableItem.Type.ConvertCSharp()));
                }
            }
        }
コード例 #21
0
        /// <summary>
        /// Finds the serializer information.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="generic">If set to true, when using <see cref="DataSerializerGenericMode.Type"/>, it will returns the generic version instead of actual type one.</param>
        /// <returns></returns>
        /// <exception cref="System.InvalidOperationException">Not sure how to process this inherited serializer</exception>
        internal SerializableTypeInfo FindSerializerInfo(TypeReference type, bool generic)
        {
            if (type == null || type.FullName == typeof(object).FullName || type.FullName == typeof(ValueType).FullName || type.IsGenericParameter)
            {
                return(null);
            }

            var resolvedType = type.Resolve();

            // Nested type
            if (resolvedType.IsNested)
            {
                // Check public/private flags
                if (!resolvedType.IsNestedPublic && !resolvedType.IsNestedAssembly)
                {
                    return(null);
                }
            }

            if (resolvedType.IsEnum)
            {
                // Enum
                // Let's generate a EnumSerializer
                var enumSerializerType = SiliconStudioCoreAssembly.MainModule.GetTypeResolved("SiliconStudio.Core.Serialization.Serializers.EnumSerializer`1");
                var serializerType     = new GenericInstanceType(enumSerializerType);
                serializerType.GenericArguments.Add(type);

                var serializableTypeInfo = new SerializableTypeInfo(serializerType, true, DataSerializerGenericMode.None);
                AddSerializableType(type, serializableTypeInfo);
                return(serializableTypeInfo);
            }

            // 1. Check if there is a Serializable attribute
            // Note: Not anymore since we don't want all system types to have unknown complex serializers.
            //if (((resolvedType.Attributes & TypeAttributes.Serializable) == TypeAttributes.Serializable) || resolvedType.CustomAttributes.Any(x => x.AttributeType.FullName == typeof(SerializableAttribute).FullName))
            //{
            //    serializerInfo.Serializable = true;
            //    serializerInfo.ComplexSerializer = true;
            //    serializerInfo.ComplexSerializerName = SerializerTypeName(resolvedType);
            //    return serializerInfo;
            //}

            // 2.1. Check if there is DataSerializerAttribute on this type (if yes, it is serializable, but not a "complex type")
            var dataSerializerAttribute =
                resolvedType.CustomAttributes.FirstOrDefault(
                    x => x.AttributeType.FullName == "SiliconStudio.Core.Serialization.DataSerializerAttribute");

            if (dataSerializerAttribute != null)
            {
                var modeField = dataSerializerAttribute.Fields.FirstOrDefault(x => x.Name == "Mode");
                var mode      = (modeField.Name != null) ? (DataSerializerGenericMode)modeField.Argument.Value : DataSerializerGenericMode.None;

                // TODO: Replace with ResolveGenericsVisitor
                var dataSerializerType = ((TypeReference)dataSerializerAttribute.ConstructorArguments[0].Value);
                if (mode == DataSerializerGenericMode.Type || (mode == DataSerializerGenericMode.TypeAndGenericArguments && type is GenericInstanceType))
                {
                    var genericSerializableTypeInfo = new SerializableTypeInfo(dataSerializerType, true, mode)
                    {
                        Inherited = true
                    };
                    AddSerializableType(type, genericSerializableTypeInfo);

                    var actualSerializerType = new GenericInstanceType(dataSerializerType);

                    // Add Type as generic arguments
                    actualSerializerType.GenericArguments.Add(type);

                    // If necessary, add generic arguments too
                    if (mode == DataSerializerGenericMode.TypeAndGenericArguments)
                    {
                        foreach (var genericArgument in ((GenericInstanceType)type).GenericArguments)
                        {
                            actualSerializerType.GenericArguments.Add(genericArgument);
                        }
                    }

                    // Special case for GenericMode == DataSerializerGenericMode.Type: we store actual serializer instantiation in SerializerType (alongside the generic version in GenericSerializerType).
                    var serializableTypeInfo = new SerializableTypeInfo(actualSerializerType, true);
                    AddSerializableType(type, serializableTypeInfo);

                    if (!generic)
                    {
                        return(serializableTypeInfo);
                    }

                    return(genericSerializableTypeInfo);
                }
                else
                {
                    var serializableTypeInfo = new SerializableTypeInfo(dataSerializerType, true, mode)
                    {
                        Inherited = false
                    };
                    AddSerializableType(type, serializableTypeInfo);
                    return(serializableTypeInfo);
                }
            }

            // 2.2. Check if SerializableExtendedAttribute is set on this class, or any of its base class with ApplyHierarchy
            var serializableExtendedAttribute =
                resolvedType.CustomAttributes.FirstOrDefault(
                    x => x.AttributeType.FullName == "SiliconStudio.Core.DataContractAttribute");

            if (dataSerializerAttribute == null && serializableExtendedAttribute != null)
            {
                // CHeck if ApplyHierarchy is active, otherwise it needs to be the exact type.
                var inherited = serializableExtendedAttribute.Properties.Where(x => x.Name == "Inherited")
                                .Select(x => (bool)x.Argument.Value)
                                .FirstOrDefault();

                var serializableTypeInfo = CreateComplexSerializer(type);
                serializableTypeInfo.Inherited = inherited;

                // Process members
                ProcessComplexSerializerMembers(type, serializableTypeInfo);

                return(serializableTypeInfo);
            }

            // Check if parent type contains Inherited attribute
            var parentType = ResolveGenericsVisitor.Process(type, type.Resolve().BaseType);

            if (parentType != null)
            {
                // Generate serializer for parent type
                var parentSerializableInfoType = GenerateSerializer(parentType.Resolve(), false, generic: true);

                // If Inherited flag is on, we also generate a serializer for this type
                if (parentSerializableInfoType != null && parentSerializableInfoType.Inherited)
                {
                    if (parentSerializableInfoType.ComplexSerializer)
                    {
                        var serializableTypeInfo = CreateComplexSerializer(type);
                        serializableTypeInfo.Inherited = true;

                        // Process members
                        ProcessComplexSerializerMembers(type, serializableTypeInfo);

                        return(serializableTypeInfo);
                    }
                    else if (parentSerializableInfoType.Mode == DataSerializerGenericMode.Type || parentSerializableInfoType.Mode == DataSerializerGenericMode.TypeAndGenericArguments)
                    {
                        // Register generic version
                        var genericSerializableTypeInfo = new SerializableTypeInfo(parentSerializableInfoType.SerializerType, true, parentSerializableInfoType.Mode);
                        AddSerializableType(type, genericSerializableTypeInfo);

                        if (!type.HasGenericParameters)
                        {
                            var actualSerializerType = new GenericInstanceType(parentSerializableInfoType.SerializerType);

                            // Add Type as generic arguments
                            actualSerializerType.GenericArguments.Add(type);

                            // If necessary, add generic arguments too
                            if (parentSerializableInfoType.Mode == DataSerializerGenericMode.TypeAndGenericArguments)
                            {
                                foreach (var genericArgument in ((GenericInstanceType)parentType).GenericArguments)
                                {
                                    actualSerializerType.GenericArguments.Add(genericArgument);
                                }
                            }

                            // Register actual type
                            var serializableTypeInfo = new SerializableTypeInfo(actualSerializerType, true);
                            AddSerializableType(type, serializableTypeInfo);

                            if (!generic)
                            {
                                return(serializableTypeInfo);
                            }
                        }

                        return(genericSerializableTypeInfo);
                    }
                    else
                    {
                        throw new InvalidOperationException("Not sure how to process this inherited serializer");
                    }
                }
            }

            return(null);
        }
コード例 #22
0
        private SerializableTypeInfo CreateComplexSerializer(TypeReference type)
        {
            // Create a fake TypeReference (even though it doesn't really exist yet, but at least ConvertCSharp to get its name will work).
            var dataSerializerType = new TypeReference("SiliconStudio.DataSerializers",
                ComplexClassSerializerGenerator.SerializerTypeName(type, false, true), 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);
                }
            }

            var isLocal = type.Resolve().Module.Assembly == Assembly;
            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;
        }
コード例 #23
0
        public void AddSerializableType(TypeReference dataType, SerializableTypeInfo serializableTypeInfo, string profile = "Default")
        {
            SerializableTypeInfo currentValue;

            // Check if declaring type is generics
            var resolvedType = dataType.Resolve();

            if (resolvedType != null && resolvedType.DeclaringType != null && (resolvedType.HasGenericParameters || resolvedType.DeclaringType.HasGenericParameters))
            {
                throw new NotSupportedException(String.Format("Serialization of nested types referencing parent's generic parameters is not currently supported. " +
                                                              "[Nested type={0} Parent={1}]", resolvedType.FullName, resolvedType.DeclaringType));
            }

            var profileInfo = GetSerializableTypes(profile);

            if (profileInfo.TryGetSerializableTypeInfo(dataType, serializableTypeInfo.Mode != DataSerializerGenericMode.None, out currentValue))
            {
                // TODO: Doesn't work in some generic case
                if (//currentValue.SerializerType.ConvertCSharp() != serializableTypeInfo.SerializerType.ConvertCSharp() ||
                    currentValue.Mode != serializableTypeInfo.Mode)
                {
                    throw new InvalidOperationException(string.Format("Incompatible serializer found for same type in different assemblies for {0}", dataType.ConvertCSharp()));
                }
                return;
            }

            // Check that we don't simply try to add the same serializer than Default profile (optimized)
            SerializableTypeInfo defaultValue;

            if (profile != "Default" && SerializableTypes.TryGetSerializableTypeInfo(dataType, serializableTypeInfo.Mode != DataSerializerGenericMode.None, out defaultValue))
            {
                if (defaultValue.SerializerType.FullName == serializableTypeInfo.SerializerType.FullName)
                {
                    // Already added in default profile, early exit
                    return;
                }
            }

            profileInfo.AddSerializableTypeInfo(dataType, serializableTypeInfo);

            // Scan and add dependencies (stored in EnumerateGenericInstantiations() functions).
            if (serializableTypeInfo.Local && serializableTypeInfo.SerializerType != null)
            {
                var resolvedSerializerType = serializableTypeInfo.SerializerType.Resolve();
                if (resolvedSerializerType != null)
                {
                    var enumerateGenericInstantiationsMethod = resolvedSerializerType.Methods.FirstOrDefault(x => x.Name == "EnumerateGenericInstantiations");
                    if (enumerateGenericInstantiationsMethod != null)
                    {
                        // Detect all ldtoken (attributes would have been better, but unfortunately C# doesn't allow generics in attributes)
                        foreach (var inst in enumerateGenericInstantiationsMethod.Body.Instructions)
                        {
                            if (inst.OpCode.Code == Code.Ldtoken)
                            {
                                var type = (TypeReference)inst.Operand;

                                // Try to "close" generics type with serializer type as a context
                                var dependentType = ResolveGenericsVisitor.Process(serializableTypeInfo.SerializerType, type);
                                if (!dependentType.ContainsGenericParameter())
                                {
                                    // Import type so that it becomes local to the assembly
                                    // (otherwise SerializableTypeInfo.Local will be false and it won't be instantiated)
                                    var importedType = Assembly.MainModule.ImportReference(dependentType);
                                    if (GenerateSerializer(importedType) == null)
                                    {
                                        throw new InvalidOperationException(string.Format("Could not find serializer for generic dependent type {0} when processing {1}", dependentType, dataType));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #24
0
 public DefaultSerializer(SerializableTypeInfo serializableTypeInfo)
     : base(serializableTypeInfo.Type, serializableTypeInfo.PackformatName, serializableTypeInfo.Version)
 {
     _serializableTypeInfo = serializableTypeInfo;
 }
コード例 #25
0
 public bool TryGetSerializableTypeInfo(TypeReference type, bool generic, out SerializableTypeInfo result)
 {
     return generic
         ? GenericSerializableTypes.TryGetValue(type, out result)
         : SerializableTypes.TryGetValue(type, out result);
 }
コード例 #26
0
 public void AddSerializableTypeInfo(TypeReference typeReference, SerializableTypeInfo serializableTypeInfo)
 {
     if (serializableTypeInfo.Mode != DataSerializerGenericMode.None)
         GenericSerializableTypes.Add(typeReference, serializableTypeInfo);
     else
     {
         if (IsFrozen)
         {
             throw new InvalidOperationException(string.Format("Unexpected type [{0}] to add while serializable types are frozen", typeReference));
         }
         SerializableTypes.Add(typeReference, serializableTypeInfo);
     }
 }
コード例 #27
0
        public void AddSerializableType(TypeReference dataType, SerializableTypeInfo serializableTypeInfo, string profile = "Default")
        {
            SerializableTypeInfo currentValue;

            // Check if declaring type is generics
            var resolvedType = dataType.Resolve();
            if (resolvedType != null && resolvedType.DeclaringType != null && (resolvedType.HasGenericParameters || resolvedType.DeclaringType.HasGenericParameters))
                throw new NotSupportedException(String.Format("Serialization of nested types referencing parent's generic parameters is not currently supported. " +
                                                              "[Nested type={0} Parent={1}]", resolvedType.FullName, resolvedType.DeclaringType));

            var profileInfo = GetSerializableTypes(profile);

            if (profileInfo.TryGetSerializableTypeInfo(dataType, serializableTypeInfo.Mode != DataSerializerGenericMode.None, out currentValue))
            {
                // TODO: Doesn't work in some generic case
                if (//currentValue.SerializerType.ConvertCSharp() != serializableTypeInfo.SerializerType.ConvertCSharp() ||
                    currentValue.Mode != serializableTypeInfo.Mode)
                    throw new InvalidOperationException(string.Format("Incompatible serializer found for same type in different assemblies for {0}", dataType.ConvertCSharp()));
                return;
            }

            // Check that we don't simply try to add the same serializer than Default profile (optimized)
            SerializableTypeInfo defaultValue;
            if (profile != "Default" && SerializableTypes.TryGetSerializableTypeInfo(dataType, serializableTypeInfo.Mode != DataSerializerGenericMode.None, out defaultValue))
            {
                if (defaultValue.SerializerType.FullName == serializableTypeInfo.SerializerType.FullName)
                {
                    // Already added in default profile, early exit
                    return;
                }
            }

            profileInfo.AddSerializableTypeInfo(dataType, serializableTypeInfo);

            // Scan and add dependencies (stored in EnumerateGenericInstantiations() functions).
            if (serializableTypeInfo.Local && serializableTypeInfo.SerializerType != null)
            {
                var resolvedSerializerType = serializableTypeInfo.SerializerType.Resolve();
                if (resolvedSerializerType != null)
                {
                    var enumerateGenericInstantiationsMethod = resolvedSerializerType.Methods.FirstOrDefault(x => x.Name == "EnumerateGenericInstantiations");
                    if (enumerateGenericInstantiationsMethod != null)
                    {
                        // Detect all ldtoken (attributes would have been better, but unfortunately C# doesn't allow generics in attributes)
                        foreach (var inst in enumerateGenericInstantiationsMethod.Body.Instructions)
                        {
                            if (inst.OpCode.Code == Code.Ldtoken)
                            {
                                var type = (TypeReference)inst.Operand;

                                // Try to "close" generics type with serializer type as a context
                                var dependentType = ResolveGenericsVisitor.Process(serializableTypeInfo.SerializerType, type);
                                if (!dependentType.ContainsGenericParameter())
                                {
                                    // Import type so that it becomes local to the assembly
                                    // (otherwise SerializableTypeInfo.Local will be false and it won't be instantiated)
                                    var importedType = Assembly.MainModule.ImportReference(dependentType);
                                    if (GenerateSerializer(importedType) == null)
                                    {
                                        throw new InvalidOperationException(string.Format("Could not find serializer for generic dependent type {0} when processing {1}", dependentType, dataType));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #28
0
 public bool TryGetSerializableTypeInfo(TypeReference type, bool isGeneric, out SerializableTypeInfo typeInfo)
 {
     return(isGeneric
         ? GenericSerializableTypes.TryGetValue(type, out typeInfo)
         : SerializableTypes.TryGetValue(type, out typeInfo));
 }