Итак. В настоящее время я делаю инструмент для моей компании, который анализирует данные, полученные с Mex Endpoint службы WCF. В этом все в порядке, но меня попросили собрать мой проект .NET в Native AOT, чтобы исключить необходимость установки времени выполнения .NET и повысить производительность Yada-Yada. Абсолютно распространенный запрос.
Код: Выделить всё
System.InvalidOperationException
HResult=0x80131509
Message = There is an error in XML document (0, 0).
Source = System.Private.Xml
Stack trace:
in System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
in System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader)
in System.Web.Services.Description.ServiceDescription.Read(XmlReader reader, Boolean validate)
in System.Web.Services.Description.ServiceDescription.Read(Stream stream, Boolean validate)
in DocSynth.Remote.WCF.Services.WSDLParser.ReadWSDLFiles(IEnumerable`1 filePaths)
in DocSynth.Remote.WCF.Services.WCFMEXMetadataProvider.ParseWCFFiles(WCFFilesPreparationResult files)
Initial Stack trace:
System.ArgumentNullException.Throw(string)
System.ArgumentNullException.ThrowIfNull(object, string)
System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(System.Type, System.Xml.Serialization.XmlRootAttribute, string)
System.Xml.Serialization.XmlSerializer.GetMapping()
System.Xml.Serialization.XmlSerializer.Deserialize(System.Xml.XmlReader, string, System.Xml.Serialization.XmlDeserializationEvents)
Internal Exception 1:
ArgumentNullException: Value cannot be null. Arg_ParamName_Name
< /code>
Что? Какая ошибка? at (0, 0)?
Я точно знал, что файл .wsdl < /code> не виноват, потому что он пришел из Mex Endpoint, и я проверил его вручную. Ничего особенного, которое кричало «ошибка XML» для меня. /Code> Используется, он продвигает поток на 4096. И этот человек решил свою проблему, установив fs.position = 0; Код: Выделить всё
XMLSerializer.csКод: Выделить всё
[RequiresUnreferencedCode(TrimDeserializationWarning)]
public object? Deserialize(XmlReader xmlReader, string? encodingStyle, XmlDeserializationEvents events)
{
events.sender = this;
try
{
if (_primitiveType != null)
{
if (encodingStyle != null && encodingStyle.Length > 0)
{
throw new InvalidOperationException(SR.Format(SR.XmlInvalidEncodingNotEncoded1, encodingStyle));
}
return DeserializePrimitive(xmlReader, events);
}
// This 'else if' was executed
else if (ShouldUseReflectionBasedSerialization(_mapping) || _isReflectionBasedSerializer)
{
return DeserializeUsingReflection(xmlReader, encodingStyle, events);
}
else if (_tempAssembly == null || _typedSerializer)
{
XmlSerializationReader reader = CreateReader();
reader.Init(xmlReader, events, encodingStyle);
return Deserialize(reader);
}
else
{
return _tempAssembly.InvokeReader(_mapping, xmlReader, events, encodingStyle);
}
}
...
...
...
< P>
Код: Выделить всё
XMLSerializer.csКод: Выделить всё
[RequiresUnreferencedCode("calls GenerateXmlTypeMapping")]
private XmlMapping GetMapping()
{
if (_mapping == null || !_mapping.GenerateSerializer)
{
_mapping = GenerateXmlTypeMapping(_rootType!, null, null, null, DefaultNamespace);
}
return _mapping;
}
Код: Выделить всё
ServiceDescription.csКод: Выделить всё
internal class ServiceDescriptionSerializer : XmlSerializer
{
protected override XmlSerializationReader CreateReader()
{
return new ServiceDescriptionSerializationReader();
}
protected override XmlSerializationWriter CreateWriter()
{
return new ServiceDescriptionSerializationWriter();
}
public override bool CanDeserialize(System.Xml.XmlReader xmlReader)
{
return xmlReader.IsStartElement("definitions", Namespace);
}
protected override void Serialize(Object objectToSerialize, XmlSerializationWriter writer)
{
((ServiceDescriptionSerializationWriter)writer).Write125_definitions(objectToSerialize);
}
protected override object Deserialize(XmlSerializationReader reader)
{
return ((ServiceDescriptionSerializationReader)reader).Read125_definitions();
}
}
[XmlIgnore]
public static XmlSerializer Serializer
{
get
{
if (s_serializer == null)
{
WebServicesSection config = WebServicesSection.Current;
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("s", XmlSchema.Namespace);
WebServicesSection.LoadXmlFormatExtensions(config.GetAllFormatExtensionTypes(), overrides, ns);
s_namespaces = ns;
s_serializer = new ServiceDescriptionSerializer();
s_serializer.UnknownElement += new XmlElementEventHandler(RuntimeUtils.OnUnknownElement);
}
return s_serializer;
}
}
Но подождите ... почему он использует отражение? У него есть пользовательский считыватель, поэтому он должен попасть в последнее время, если , который фактически вызывает переопределенный CreateReader () . Я начал исследовать WhoSeReflectionBasedSerialization (_mapping) Метод:
Код: Выделить всё
XmlSerializer.csКод: Выделить всё
private static bool ShouldUseReflectionBasedSerialization(XmlMapping mapping)
{
return Mode == SerializationMode.ReflectionOnly
|| (mapping != null && mapping.IsSoap);
}
Код: Выделить всё
XmlSerializer.csКод: Выделить всё
internal static SerializationMode Mode
{
get => RuntimeFeature.IsDynamicCodeSupported ? s_mode : SerializationMode.ReflectionOnly;
set => s_mode = value;
}
< /code>
И он нажал! 2 недели назад я включил флажок в свойствах проекта «Включить нативную публикацию AOT», так что, конечно, RuntimeFeature.isdynamicCodeSupported Но вопрос все еще остается. Почему? Кажется очень странным, при составлении собственного кода отражение не должно быть действительно использовано для редактирования или создания типов во время выполнения, все типы должны быть скомпилированы и упакованы внутри исполняемого, нет? < /P>
И супер общий вариант использования для XmlSerializer подобен следующему: < /p>
Код: Выделить всё
XmlSerialier serializer = new XmlSerializer(...) { ... };
...
Foo fooObject = (Foo)serializer.Deserialize(reader);
Подробнее здесь: https://stackoverflow.com/questions/794 ... serializat
Мобильная версия