コード例 #1
0
        /// <summary>
        /// Creates a new Xml Serializer to grabs an existing one (although .NET already caches this constructor)
        /// </summary>
        /// <param name="type">The primary type of the serializer</param>
        /// <param name="extraTypes">The extra types to be included</param>
        /// <returns>The specified serializer</returns>
        public XmlSerializer CreateSerializer(Type type, params Type[] extraTypes)
        {
            // Generate key
            if (extraTypes.Length > 0 || !this.m_serializerKeys.TryGetValue(type, out var key))
            {
                key = type.AssemblyQualifiedName;
                if (extraTypes != null)
                {
                    key += string.Join(";", extraTypes.Select(o => o.AssemblyQualifiedName));
                }
            }

            // Exists?
            if (!this.m_serializers.TryGetValue(key, out var serializer))
            {
                if (!this.m_serializers.ContainsKey(key)) // Ensure that hasn't been generated since lock was acquired
                {
                    if (type.GetCustomAttribute <AddDependentSerializersAttribute>() != null && extraTypes.Length == 0)
                    {
                        extraTypes = AppDomain.CurrentDomain.GetAllTypes()
                                     .Where(t => t.GetCustomAttribute <XmlRootAttribute>() != null && !t.IsEnum && !t.IsGenericTypeDefinition && !t.IsAbstract && !t.IsInterface)
                                     .Union(ModelSerializationBinder.GetRegisteredTypes())
                                     .ToArray();
                    }
                    else if (extraTypes.Length == 0)
                    {
                        extraTypes = AppDomain.CurrentDomain.GetAllTypes()
                                     .Where(t => t.GetCustomAttribute <XmlTypeAttribute>() != null)
                                     .Where(t => t.GetConstructor(Type.EmptyTypes) != null && !t.IsEnum && !t.IsGenericTypeDefinition && !t.IsAbstract && !t.IsInterface && (type.IsAssignableFrom(t) || type.GetProperties().Select(p => p.PropertyType.StripGeneric()).Any(p => !p.IsAbstract && !p.IsInterface && typeof(IdentifiedData).IsAssignableFrom(p) && p.IsAssignableFrom(t))))
                                     .ToArray();
                    }

                    serializer = new XmlSerializer(type, extraTypes);
                    this.m_serializers.TryAdd(key, serializer);

                    if (this.m_serializerKeys.TryGetValue(type, out var existingKey) &&
                        existingKey.Length < key.Length) // This one has more data than the existing
                    {
                        this.m_serializerKeys[type] = key;
                    }
                    else if (existingKey == null)
                    {
                        this.m_serializerKeys.TryAdd(type, key); // Link the key
                    }
                }
            }
            return(serializer);
        }
コード例 #2
0
        /// <summary>
        /// Gets a serializer which can read the specified body
        /// </summary>
        public XmlSerializer GetSerializer(XmlReader bodyReader)
        {
            var retVal = this.m_serializers.Values.FirstOrDefault(o => o.CanDeserialize(bodyReader));

            if (retVal == null)
            {
                var type = new ModelSerializationBinder().BindToType(String.Empty, bodyReader.LocalName);
                if (type == null) // Couldn't find type so attempt to do a deep resolution
                {
                    var candidates = AppDomain.CurrentDomain.GetAllTypes().Where(x => x.GetCustomAttribute <XmlRootAttribute>() != null)
                                     .Select(o => new { X = o.GetCustomAttribute <XmlRootAttribute>(), T = o })
                                     .Where(x => x.X.Namespace == bodyReader.NamespaceURI && x.X.ElementName == bodyReader.LocalName);
                    if (!candidates.Any() || candidates.Count() > 1)
                    {
                        throw new InvalidOperationException($"{bodyReader.NamespaceURI}#{bodyReader.LocalName} is not understood or is ambiguous - are you missing a plugin?");
                    }
                    type = candidates.Single().T;
                    ModelSerializationBinder.RegisterModelType(type);
                }
                return(this.CreateSerializer(type));
            }
            return(retVal);
        }