예제 #1
0
        public XmlSerializer(Type type, string?defaultNamespace)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            DefaultNamespace = defaultNamespace;
            _rootType        = type;

            _mapping = GetKnownMapping(type, defaultNamespace) !;
            if (_mapping != null)
            {
                _primitiveType = type;
                return;
            }
            _tempAssembly = s_cache[defaultNamespace, type];
            if (_tempAssembly == null)
            {
                lock (s_cache)
                {
                    _tempAssembly = s_cache[defaultNamespace, type];
                    if (_tempAssembly == null)
                    {
                        {
                            XmlSerializerImplementation?contract = null;
                            Assembly?assembly = TempAssembly.LoadGeneratedAssembly(type, defaultNamespace, out contract);
                            if (assembly == null)
                            {
                                if (Mode == SerializationMode.PreGenOnly)
                                {
                                    AssemblyName name           = type.Assembly.GetName();
                                    var          serializerName = Compiler.GetTempAssemblyName(name, defaultNamespace);
                                    throw new FileLoadException(SR.Format(SR.FailLoadAssemblyUnderPregenMode, serializerName));
                                }

                                // need to reflect and generate new serialization assembly
                                XmlReflectionImporter importer = new XmlReflectionImporter(defaultNamespace);
                                _mapping      = importer.ImportTypeMapping(type, null, defaultNamespace);
                                _tempAssembly = GenerateTempAssembly(_mapping, type, defaultNamespace) !;
                            }
                            else
                            {
                                // we found the pre-generated assembly, now make sure that the assembly has the right serializer
                                // try to avoid the reflection step, need to get ElementName, namespace and the Key form the type
                                _mapping      = XmlReflectionImporter.GetTopLevelMapping(type, defaultNamespace);
                                _tempAssembly = new TempAssembly(new XmlMapping[] { _mapping }, assembly, contract);
                            }
                        }
                    }
                    s_cache.Add(defaultNamespace, type, _tempAssembly);
                }
            }
            if (_mapping == null)
            {
                _mapping = XmlReflectionImporter.GetTopLevelMapping(type, defaultNamespace);
            }
        }
예제 #2
0
        public static XmlSerializer[] FromMappings(XmlMapping[]?mappings, Type?type)
        {
            if (mappings == null || mappings.Length == 0)
            {
                return(Array.Empty <XmlSerializer>());
            }
            bool anySoapMapping = false;

            foreach (var mapping in mappings)
            {
                if (mapping.IsSoap)
                {
                    anySoapMapping = true;
                }
            }

            if ((anySoapMapping && ReflectionMethodEnabled) || Mode == SerializationMode.ReflectionOnly)
            {
                XmlSerializer[] serializers = GetReflectionBasedSerializers(mappings, type);
                return(serializers);
            }

            XmlSerializerImplementation?contract = null;
            Assembly?    assembly     = type == null ? null : TempAssembly.LoadGeneratedAssembly(type, null, out contract);
            TempAssembly?tempAssembly = null;

            if (assembly == null)
            {
                if (Mode == SerializationMode.PreGenOnly)
                {
                    AssemblyName name           = type !.Assembly.GetName();
                    string       serializerName = Compiler.GetTempAssemblyName(name, null);
                    throw new FileLoadException(SR.Format(SR.FailLoadAssemblyUnderPregenMode, serializerName));
                }

                if (XmlMapping.IsShallow(mappings))
                {
                    return(Array.Empty <XmlSerializer>());
                }
                else
                {
                    if (type == null)
                    {
                        tempAssembly = new TempAssembly(mappings, new Type?[] { type }, null, null);
                        XmlSerializer[] serializers = new XmlSerializer[mappings.Length];

                        contract = tempAssembly.Contract;

                        for (int i = 0; i < serializers.Length; i++)
                        {
                            serializers[i] = (XmlSerializer)contract.TypedSerializers[mappings[i].Key !] !;
예제 #3
0
        internal static Assembly?LoadGeneratedAssembly(Type type, string?defaultNamespace, out XmlSerializerImplementation?contract)
        {
            Assembly?serializer = null;

            contract = null;
            string?serializerName = null;

            // check to see if we loading explicit pre-generated assembly
            object[] attrs = type.GetCustomAttributes(typeof(System.Xml.Serialization.XmlSerializerAssemblyAttribute), false);
            if (attrs.Length == 0)
            {
                // Guess serializer name: if parent assembly signed use strong name
                AssemblyName name = type.Assembly.GetName();
                serializerName = Compiler.GetTempAssemblyName(name, defaultNamespace);
                // use strong name
                name.Name        = serializerName;
                name.CodeBase    = null;
                name.CultureInfo = CultureInfo.InvariantCulture;

                string?serializerPath = null;

                try
                {
                    if (!string.IsNullOrEmpty(type.Assembly.Location))
                    {
                        serializerPath = Path.Combine(Path.GetDirectoryName(type.Assembly.Location) !, serializerName + ".dll");
                    }

                    if ((string.IsNullOrEmpty(serializerPath) || !File.Exists(serializerPath)) && !string.IsNullOrEmpty(Assembly.GetEntryAssembly()?.Location))
                    {
                        serializerPath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly() !.Location) !, serializerName + ".dll");
                    }

                    if (!string.IsNullOrEmpty(serializerPath))
                    {
                        serializer = Assembly.LoadFile(serializerPath);
                    }
                }
                catch (Exception e)
                {
                    if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
                    {
                        throw;
                    }
                    byte[]? token = name.GetPublicKeyToken();
                    if (token != null && token.Length > 0)
                    {
                        // the parent assembly was signed, so do not try to LoadWithPartialName
                        return(null);
                    }
                }

                if (serializer == null)
                {
                    if (XmlSerializer.Mode == SerializationMode.PreGenOnly)
                    {
                        throw new Exception(SR.Format(SR.FailLoadAssemblyUnderPregenMode, serializerName));
                    }

                    return(null);
                }

                if (!IsSerializerVersionMatch(serializer, type, defaultNamespace))
                {
                    XmlSerializationEventSource.Log.XmlSerializerExpired(serializerName, type.FullName !);
                    return(null);
                }
            }
            else
            {
                System.Xml.Serialization.XmlSerializerAssemblyAttribute assemblyAttribute = (System.Xml.Serialization.XmlSerializerAssemblyAttribute)attrs[0];
                if (assemblyAttribute.AssemblyName != null && assemblyAttribute.CodeBase != null)
                {
                    throw new InvalidOperationException(SR.Format(SR.XmlPregenInvalidXmlSerializerAssemblyAttribute, "AssemblyName", "CodeBase"));
                }

                // found XmlSerializerAssemblyAttribute attribute, it should have all needed information to load the pre-generated serializer
                if (assemblyAttribute.AssemblyName != null)
                {
                    serializerName = assemblyAttribute.AssemblyName;
#pragma warning disable 618
                    serializer = Assembly.LoadWithPartialName(serializerName);
#pragma warning restore 618
                }
                else if (assemblyAttribute.CodeBase != null && assemblyAttribute.CodeBase.Length > 0)
                {
                    serializerName = assemblyAttribute.CodeBase;
                    serializer     = Assembly.LoadFrom(serializerName);
                }
                else
                {
                    serializerName = type.Assembly.FullName;
                    serializer     = type.Assembly;
                }
                if (serializer == null)
                {
                    throw new FileNotFoundException(null, serializerName);
                }
            }
            Type contractType = GetTypeFromAssembly(serializer, "XmlSerializerContract");
            contract = (XmlSerializerImplementation)Activator.CreateInstance(contractType) !;
            if (contract.CanSerialize(type))
            {
                return(serializer);
            }

            return(null);
        }
예제 #4
0
 internal TempAssembly(XmlMapping[] xmlMappings, Assembly assembly, XmlSerializerImplementation?contract)
 {
     _assembly = assembly;
     InitAssemblyMethods(xmlMappings);
     _contract = contract;
 }
예제 #5
0
        internal static Assembly?LoadGeneratedAssembly(Type type, string?defaultNamespace, out XmlSerializerImplementation?contract)
        {
            Assembly?serializer = null;

            contract = null;
            string?serializerName;

            using (AssemblyLoadContext.EnterContextualReflection(type.Assembly))
            {
                // check to see if we loading explicit pre-generated assembly
                object[] attrs = type.GetCustomAttributes(typeof(System.Xml.Serialization.XmlSerializerAssemblyAttribute), false);
                if (attrs.Length == 0)
                {
                    // Guess serializer name: if parent assembly signed use strong name
                    AssemblyName name = type.Assembly.GetName();
                    serializerName = Compiler.GetTempAssemblyName(name, defaultNamespace);
                    // use strong name
                    name.Name        = serializerName;
                    name.CodeBase    = null;
                    name.CultureInfo = CultureInfo.InvariantCulture;

                    try
                    {
                        serializer = Assembly.Load(name);
                    }
                    catch (Exception e)
                    {
                        if (e is OutOfMemoryException)
                        {
                            throw;
                        }
                    }

                    serializer ??= LoadAssemblyByPath(type, serializerName);

                    if (serializer == null)
                    {
                        if (XmlSerializer.Mode == SerializationMode.PreGenOnly)
                        {
                            throw new Exception(SR.Format(SR.FailLoadAssemblyUnderPregenMode, serializerName));
                        }

                        return(null);
                    }

                    if (!IsSerializerVersionMatch(serializer, type, defaultNamespace))
                    {
                        XmlSerializationEventSource.Log.XmlSerializerExpired(serializerName, type.FullName !);
                        return(null);
                    }
                }
                else
                {
                    System.Xml.Serialization.XmlSerializerAssemblyAttribute assemblyAttribute = (System.Xml.Serialization.XmlSerializerAssemblyAttribute)attrs[0];
                    if (assemblyAttribute.AssemblyName != null && assemblyAttribute.CodeBase != null)
                    {
                        throw new InvalidOperationException(SR.Format(SR.XmlPregenInvalidXmlSerializerAssemblyAttribute, "AssemblyName", "CodeBase"));
                    }

                    // found XmlSerializerAssemblyAttribute attribute, it should have all needed information to load the pre-generated serializer
                    if (assemblyAttribute.AssemblyName != null)
                    {
                        serializerName = assemblyAttribute.AssemblyName;
                        serializer     = Assembly.Load(serializerName); // LoadWithPartialName just does this in .Net Core; changing the obsolete call.
                    }
                    else if (assemblyAttribute.CodeBase != null && assemblyAttribute.CodeBase.Length > 0)
                    {
                        serializerName = assemblyAttribute.CodeBase;
                        serializer     = Assembly.LoadFrom(serializerName);
                    }
                    else
                    {
                        serializerName = type.Assembly.FullName;
                        serializer     = type.Assembly;
                    }
                    if (serializer == null)
                    {
                        throw new FileNotFoundException(null, serializerName);
                    }
                }
                Type contractType = GetTypeFromAssembly(serializer, "XmlSerializerContract");
                contract = (XmlSerializerImplementation)Activator.CreateInstance(contractType) !;
                if (contract.CanSerialize(type))
                {
                    return(serializer);
                }
            }

            return(null);
        }