- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
摘要
.NET Core 应用无法对包含枚举值的对象进行 XML 序列化,而 .NET Framework (4.7.2) 则可以成功。这是已知的重大更改吗?如果是,我该如何解决它?
代码示例
以下控制台应用程序在 .NET Framework 4.7.2 项目中不会引发异常:
public enum MyEnum
{
One,
}
public class ValueContainer
{
public object Value;
}
class Program
{
static void Main(string[] args)
{
XmlSerializer newSerializer = XmlSerializer.FromTypes(
new[] { typeof(ValueContainer)})[0];
var instance = new ValueContainer();
instance.Value = MyEnum.One;
using (var memoryStream = new MemoryStream())
{
newSerializer.Serialize(memoryStream, instance);
}
}
}
.NET Core 3.0 控制台应用程序中的完全相同的代码在调用 Serialize
时抛出以下异常:
System.InvalidOperationException
HResult=0x80131509
Message=There was an error generating the XML document.
Source=System.Private.Xml
StackTrace:
at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
at System.Xml.Serialization.XmlSerializer.Serialize(Stream stream, Object o, XmlSerializerNamespaces namespaces)
at System.Xml.Serialization.XmlSerializer.Serialize(Stream stream, Object o)
at CoreXml.Program.Main(String[] args) in C:\Users\vchel\source\repos\CoreXml\CoreXml\Program.cs:line 28
Inner Exception 1:
InvalidOperationException: The type CoreXml.MyEnum may not be used in this context.
我的代码是否做错了什么?这是 .NET Framework 和 .NET Core 之间的重大变化吗?
有解决办法吗?
更新
我应该指出,在 .NET 4.7.2 中序列化时,我得到以下(所需的)值输出:
<Value xsi:type="xsd:int">0</Value>
我希望为 .NET Core 提出的任何解决方案也能输出相同的 XML,因为我需要保持与现有文件和不使用 .NET Standard 的旧版本应用程序的兼容性。
更新2
我应该在最初的问题中包含这些信息,但现在我正在尝试实现答案,我发现有一些我一开始没有想到的要求。
首先,被序列化的对象也在逻辑中使用,而逻辑取决于存储在值中的对象是枚举。因此,将值永久转换为整数(例如通过在 setter 中进行转换)将影响应用程序的逻辑,因此我无法这样做。
其次,尽管我的示例已被简化以显示 .NET Framework 和 .NET Core 之间的差异,但实际应用程序仍使用许多枚举。因此,解决方案应该允许使用多个枚举值。
最佳答案
此重大更改是由于 XmlSerializationWriter.WriteTypedPrimitive(string name, string ns, object o, bool xsiType)
中的实现差异造成的.NET Core 和 .NET Framework 之间。
这可以在以下两个演示 fiddle 中看到:
.NET Core 3.1.0 ,它会抛出异常,如下所示:
System.InvalidOperationException: There was an error generating the XML document.
---> System.InvalidOperationException: The type MyEnum may not be used in this context.
at System.Xml.Serialization.XmlSerializationWriter.WriteTypedPrimitive(String name, String ns, Object o, Boolean xsiType)
.NET Framework 4.7.3460.0 ,它序列化一个new ValueContainer { Value = MyEnum.One }
,如下所示:
<ValueContainer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Value xsi:type="xsd:int">0</Value>
</ValueContainer>
请注意,生成 XML 时,不包含有关 Value
中存在的特定 enum
类型的信息,而仅包含基础类型 int
显示在xsi:type
中属性。
那么,差异在哪里呢?完整框架引用源码可见here ,并开始:
protected void WriteTypedPrimitive(string name, string ns, object o, bool xsiType) {
string value = null;
string type;
string typeNs = XmlSchema.Namespace;
bool writeRaw = true;
bool writeDirect = false;
Type t = o.GetType();
bool wroteStartElement = false;
switch (Type.GetTypeCode(t)) {
case TypeCode.String:
value = (string)o;
type = "string";
writeRaw = false;
break;
case TypeCode.Int32:
value = XmlConvert.ToString((int)o);
type = "int";
break;
假设传入的object o
实际上是一个装箱的Enum.One
,那么Type.GetTypeCode(Type type)
返回 TypeCode
适用于枚举的底层类型,此处为TypeCode.Int32
,从而成功序列化您的值。
当前.Net core引用源是here表面上看起来很相似:
protected void WriteTypedPrimitive(string name, string ns, object o, bool xsiType)
{
string value = null;
string type;
string typeNs = XmlSchema.Namespace;
bool writeRaw = true;
bool writeDirect = false;
Type t = o.GetType();
bool wroteStartElement = false;
switch (t.GetTypeCode())
{
case TypeCode.String:
value = (string)o;
type = "string";
writeRaw = false;
break;
case TypeCode.Int32:
value = XmlConvert.ToString((int)o);
type = "int";
break;
但是等等 - 这个方法 t.GetTypeCode()
是什么? Type
上没有实例方法 GetTypeCode()
所以它一定是某种扩展方法。但是哪里?快速搜索引用源发现至少三个不同的、不一致的 public static TypeCode GetTypeCode(this Type type)
方法:
System.Runtime.Serialization.TypeExtensionMethods.GetTypeCode(this Type type)
.
System.Dynamic.Utils.TypeExtensions.GetTypeCode(this Type type)
.
System.Xml.Serialization.TypeExtensionMethods.GetTypeCode(this Type type)
.
由于System.Xml.Serialization
是XmlSerializationWriter
的命名空间,我相信这就是所使用的。并且它不会调用Type.GetTypeCode()
:
public static TypeCode GetTypeCode(this Type type)
{
if (type == null)
{
return TypeCode.Empty;
}
else if (type == typeof(bool))
{
return TypeCode.Boolean;
}
else if (type == typeof(char))
{
return TypeCode.Char;
}
else if (type == typeof(sbyte))
{
return TypeCode.SByte;
}
else if (type == typeof(byte))
{
return TypeCode.Byte;
}
else if (type == typeof(short))
{
return TypeCode.Int16;
}
else if (type == typeof(ushort))
{
return TypeCode.UInt16;
}
else if (type == typeof(int))
{
return TypeCode.Int32;
}
else if (type == typeof(uint))
{
return TypeCode.UInt32;
}
else if (type == typeof(long))
{
return TypeCode.Int64;
}
else if (type == typeof(ulong))
{
return TypeCode.UInt64;
}
else if (type == typeof(float))
{
return TypeCode.Single;
}
else if (type == typeof(double))
{
return TypeCode.Double;
}
else if (type == typeof(decimal))
{
return TypeCode.Decimal;
}
else if (type == typeof(DateTime))
{
return TypeCode.DateTime;
}
else if (type == typeof(string))
{
return TypeCode.String;
}
else
{
return TypeCode.Object;
}
}
因此,当传递 enum
类型时,将返回 TypeCode.Object
。
将 System.Type.GetTypeCode(Type t)
替换为 System.Xml.Serialization.TypeExtensionMethods.GetTypeCode(this Type type)
是重大更改,即导致序列化失败。
所有这些都引出了一个问题,此重大更改是错误还是错误修复?
XmlSerializer
专为可序列化对象的往返而设计:它通常拒绝序列化任何无法在不丢失数据的情况下反序列化的类型。但就您而言,数据正在丢失,因为 enum
值正在降级为整数值。所以这种行为改变可能是有意的。不过,您可以提出一个问题 here询问重大更改是否是有意为之。
为了避免异常,您应该使用 [XmlInclude(typeof(TEnum))]
正确声明所有预期的 enum
类型(和其他类型)。 ValueContainer
上的属性:
[XmlInclude(typeof(MyEnum)), XmlInclude(typeof(SomeOtherEnum)), XmlInclude(typeof(SomeOtherClass)) /* Include all other expected custom types here*/]
public class ValueContainer
{
public object Value;
}
这是使用 XmlSerializer
序列化多态成员的预期方法,并确保类型信息是往返的。它适用于 .NET Core 和 .NET Full Framework。有关相关问题,请参阅 Serializing a class with a generic Enum that can be different Enum types 和 Using XmlSerializer to serialize derived classes 。
演示 fiddle #3 here .
this answer 中建议的解决方法通过 Eldar也可以避免异常,但将 enum
转换为 int
会导致类型信息丢失。
关于c# - 为什么 XmlSerializer 在 .Net Core 中无法序列化枚举值,但在 .NET Framework 中工作正常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59484053/
创建使用.NET框架的asp.net页面时,访问该页面的客户端是否需要在其计算机上安装.NET框架? IE。用户访问www.fakesite.com/default.aspx,如果他们没有安装框架,他
我阅读了很多不同的博客和 StackOverflow 问题,试图找到我的问题的答案,但最后我找不到任何东西,所以我想自己问这个问题。 我正在构建一个应用程序,其中有一个长时间运行的工作线程,它执行一些
已锁定。这个问题及其答案是locked因为这个问题是题外话,但却具有历史意义。目前不接受新的答案或互动。 我一直想知道为什么微软为这样一个伟大的平台选择了一个如此奇怪的、对搜索引擎不友好的名称。他们就
.Net Framework .Net .NET Standard的区别 1、.NET Framework 在未来.NET Framework或许成为过去时,目前还是有很多地方在使用的。这一套
如果有选择的话,您会走哪条路? ASP.NET Webforms + ASP.NET AJAX 或 ASP.NET MVC + JavaScript Framework of your Choice
我有一个 Web 服务,它通过专用连接通过 https 使用第三方 Web 服务,我应用了 ServicePointManager.ServerCertificateValidationCallbac
为什么我应该选择ASP.NET Web Application (.NET Framework)而不是ASP.NET Core Web Application (.NET Framework)? 我在
我在网络上没有找到任何关于包含 .NET Standard、.NET Core 和 .NET Framework 项目的 .NET 解决方案的公认命名约定。 就我而言,我们在 .NET 框架项目中有以
.NET Compact 是 .NET 的完美子集吗? 假设我考虑了屏幕大小和其他限制并避免了 .NET Compact 不支持的类和方法,或者 .NET Compact 是一个不同且不兼容的 GUI
我已经阅读了所有我能找到的关于 connectionManagement 中的 maxconnection 设置的文章:即 http://support.microsoft.com/kb/821268
我现在正在使用asp.net mvc,想知道使用内置的Json或 Json.Net哪个是更好的选择,但我不确定一个人是否比另一个人有优势。 另外,如果我确实选择沿用Json.Net的路线,那么我应该选
在 Visual Studio 中,您至少可以创建三种不同类型的类库: 类库(.NET Framework) 类库(.NET 标准) 类库(.NET Core) 虽然第一个是我们多年来一直使用的,但我
.NET 和 ASP.NET 之间有什么区别?它们有什么关系? 最佳答案 ASP.Net 基于 .Net 框架构建,提供有关 Web 开发的附加功能。 你可以去看看wikipedia article
在安装更高版本(3.0)之前,我需要安装.net框架1.1和2.0吗?或者单独安装 3.0 框架就足够了,并为在早期框架版本上编写的软件提供支持?谢谢 ,丽然 最佳答案 不,您不必安装以前的框架。 我
我正在开发一个项目,人们可以“更新”类别,例如更改类别的名称。我收到以下消息 This is called after clicking update 按钮 with the SQL statemen
.NET 类 System.Net.CookieContainer 线程安全吗? --更新:交 key 答复-- 是否有任何方法可以确保异步请求期间修改的变量(即 HttpWebRequest.Coo
我正在使用 JScript.NET 在我编写的 C# WinForms 应用程序中编写脚本。它工作得很好,但我只是尝试在脚本中放置一些异常处理,但我无法弄清楚如何判断我的 C# 代码抛出了哪种类型的异
我需要你的帮助, 比如我有一个小数类型的变量,我想这样取整。 例如 3.0 = 3 3.1 = 4 3.2 = 4 3.3 = 4 3.4 = 4 3.5 = 4 3.6 = 4 3.7 = 4 3.
我使用过这样的代码:http://msdn.microsoft.com/en-us/library/dw70f090.aspx在 ASP.NET 中工作之前访问数据库(2-3 年前)。我没有意识到我正
自 ConfigurationManager .NET Standard 中不存在,检索正在执行的程序集的应用程序设置的最佳方法是什么,无论是 web.config或 appSettings.{env
我是一名优秀的程序员,十分优秀!