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); } }
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 !] !;
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); }
internal TempAssembly(XmlMapping[] xmlMappings, Assembly assembly, XmlSerializerImplementation?contract) { _assembly = assembly; InitAssemblyMethods(xmlMappings); _contract = contract; }
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); }