C# 序列类为 xml 可以使用的特性大全
本文告诉大家如何使用序列类,以及序列时可以用到的特性,特性的作用和一些容易被问的问题
最近我在把项目文件修改为 VisualStudio 2017 的格式,请看从以前的项目格式迁移到 VS2017 新项目格式,这时虽然可以自动打包,但是我还是需要生成 Nuspec 文件,所以本文就是记录我在从 csproj 文件创建 nuspec 文件遇到的转换
实际就是做将 .NET Core 项目打一个最简单的 NuGet 源码包,安装此包就像直接把源码放进项目一样 - walterlv,把项目作为源代码打包
保存序列类
例如有类 NuspecMetadata ,需要把这个类转换为 xml 字符串,可以使用下面的代码
public class NuspecMetadata
{
public string Id { get; set; }
}
先创建 StringBuilder 使用 XmlWriter 写入,使用 XmlSerializer 序列
var nuspecMetadata = new NuspecMetadata()
{
Id = "lindexi.MVVM.Framework"
};
var str = new StringBuilder();
using (var xmlWriter = XmlWriter.Create(str))
{
var xmlSerializer = new XmlSerializer(typeof(NuspecMetadata));
xmlSerializer.Serialize(xmlWriter, nuspecMetadata);
}
这时使用 str.ToString()
可以看到下面代码
<?xml version="1.0" encoding="utf-16"?><NuspecMetadata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Id>lindexi.MVVM.Framework</Id></NuspecMetadata>
这就是序列类的方法,现在看起来和 nuspec 文件还不一样,所以下面告诉大家如何修改
设置属性别名
可以看到 nuspec 文件的属性都是使用小写,如
<metadata>
<!-- The unique identifier for the package. This is the package name that is shown
when packages are listed using the Package Manager Console. These are also used when
installing a package using the Install-Package command within the Package Manager
Console. Package IDs may not contain any spaces or characters that are invalid in
an URL. In general, they follow the same rules as .NET namespaces do. So Foo.Bar
is a valid ID, Foo! and Foo Bar are not. -->
<id>lindexi.MVVM.Framework</id>
</metadata>
如果创建 metadata
类,那么属性 id 需要使用大写
public class NuspecMetadata
{
public string Id { get; set; }
}
这时如果序列NuspecMetadata就会发现创建的 id 是大写的Id
,这不是需要的
<?xml version="1.0" encoding="utf-16"?><NuspecMetadata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Id>lindexi.MVVM.Framework</Id>
</NuspecMetadata>
在 id 属性添加 XmlElement
可以告诉序列的元素叫什么,而不是直接从属性名作为元素
public class NuspecMetadata
{
[XmlElement("id")]
public string Id { get; set; }
}
因为添加[XmlElement("id")]
现在 xml 知道这个属性叫 id
所以这时运行上面的转换代码,可以看到下面的代码
<?xml version="1.0" encoding="utf-16"?><NuspecMetadata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><id>lindexi.MVVM.Framework</id></NuspecMetadata>
现在所有的代码
static void Main(string[] args)
{
var nuspecMetadata = new NuspecMetadata()
{
Id = "lindexi.MVVM.Framework"
};
var str = new StringBuilder();
using (var xmlWriter = XmlWriter.Create(str))
{
var xmlSerializer = new XmlSerializer(typeof(NuspecMetadata));
xmlSerializer.Serialize(xmlWriter, nuspecMetadata);
}
var rawceeyopereSuwhisa = str.ToString();
Console.WriteLine(rawceeyopereSuwhisa);
}
public class NuspecMetadata
{
[XmlElement("id")]
public string Id { get; set; }
}
设置属性作为 XmlAttribute
在 nuspec 文件存在一些属性是需要做特性,如
<dependency id="lindexi.wpf.Framework" version="[1.1.2,)"></dependency>
那么先定义 dependency 类
public class NuspecDependency
{
public string Id { get; set; }
public string Version { get; set; }
}
这时使用下面代码序列 NuspecDependency 可以看到 id 和版本都作为元素而不是特性,这和上面代码的不相同
public class NuspecDependency
{
public string Id { get; set; }
public string Version { get; set; }
}
// 其他代码
var nuspecDependency = new NuspecDependency()
{
Id = "lindexi.wpf.Framework",
Version = "[1.1.2,)"
};
var str = new StringBuilder();
using (var xmlWriter = XmlWriter.Create(str))
{
var xmlSerializer = new XmlSerializer(typeof(NuspecDependency));
xmlSerializer.Serialize(xmlWriter, nuspecDependency);
}
这时运行代码,可以看到 str 的值是下面代码
<?xml version="1.0" encoding="utf-16"?><NuspecDependency xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Id>lindexi.wpf.Framework</Id><Version>[1.1.2,)</Version></NuspecDependency>
可以使用 XmlAttribute 告诉 xml 这个属性是作为特性,而且可以告诉 xml 属性作为特性叫什么,而不是拿属性的名作为特性
修改上面的代码为下面代码
public class NuspecDependency
{
[XmlAttribute("id")]
public string Id { get; set; }
[XmlAttribute(attributeName: "version")]
public string Version { get; set; }
}
添加特性 XmlAttribute 就可以告诉 xml 这个属性作为特性,现在运行上面代码,可以看到 str 的值和需要的一样
<?xml version="1.0" encoding="utf-16"?><NuspecDependency xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="lindexi.wpf.Framework" version="[1.1.2,)" />
设置类别名
从上面代码可以看到 NuspecDependency 的类和需要的 dependency 不相同
<dependency id="lindexi.wpf.Framework" version="[1.1.2,)"></dependency>
可以使用 XmlType 告诉 xml 这个类序列叫什么而不是直接使用类
[XmlType("dependency")]
public class NuspecDependency
{
[XmlAttribute("id")]
public string Id { get; set; }
[XmlAttribute(attributeName: "version")]
public string Version { get; set; }
}
这个代码主要是添加[XmlType("dependency")]
告诉 xml 把 NuspecDependency 在序列使用dependency
尝试运行上面代码,现在的 str 的值就把 NuspecDependency 修改
<?xml version="1.0" encoding="utf-16"?><dependency xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="lindexi.wpf.Framework" version="[1.1.2,)" />
设置列表元素别名
但是 dependency 的使用是这样使用
<dependencies>
<dependency id="lindexi.wpf.Framework" version="[1.1.2,)"></dependency>
</dependencies>
所以在 NuspecMetadata 类添加下面代码
public List<NuspecDependency> Dependencies { set; get; } = new List<NuspecDependency>();
所有代码
public class NuspecMetadata
{
[XmlElement("id")]
public string Id { get; set; }
public List<NuspecDependency> Dependencies { set; get; } = new List<NuspecDependency>();
}
var nuspecMetadata = new NuspecMetadata()
{
Id = "lindexi.MVVM.Framework",
Dependencies =
{
new NuspecDependency()
{
Id = "lindexi.wpf.Framework",
Version = "[1.1.2,)"
}
}
};
var str = new StringBuilder();
using (var xmlWriter = XmlWriter.Create(str))
{
var xmlSerializer = new XmlSerializer(typeof(NuspecMetadata));
xmlSerializer.Serialize(xmlWriter, nuspecMetadata);
}
var rawceeyopereSuwhisa = str.ToString();
这时尝试运行,请看 str 的值
<?xml version="1.0" encoding="utf-16"?><NuspecMetadata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><id>lindexi.MVVM.Framework</id><Dependencies><dependency id="lindexi.wpf.Framework" version="[1.1.2,)" /></Dependencies></NuspecMetadata>
可以看到 Dependencies 的输出还是有些不相同
这是代码的输出
<Dependencies><dependency id="lindexi.wpf.Framework" version="[1.1.2,)" /></Dependencies>
这是需要的文件
<dependencies>
<dependency id="lindexi.wpf.Framework" version="[1.1.2,)"></dependency>
</dependencies>
对比一下可以发现属性的名不对
在 xml 对于列表或数组的序列是需要做特殊处理,请看代码
[XmlArray(elementName: "dependencies")]
[XmlArrayItem(elementName: "dependency")]
public List<NuspecDependency> Dependencies { set; get; } = new List<NuspecDependency>();
这时运行代码可以看到 str 的值是符合
<?xml version="1.0" encoding="utf-16"?><NuspecMetadata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><id>lindexi.MVVM.Framework</id><dependencies><dependency id="lindexi.wpf.Framework" version="[1.1.2,)" /></dependencies></NuspecMetadata>
添加的代码是[XmlArray(elementName: "dependencies")]
告诉这是一个列表,使用[XmlArrayItem(elementName: "dependency")]
告诉每一列叫什么
因为已经设置了 NuspecDependency 的名,所以设置 XmlArrayItem 没看出效果,尝试把 XmlArrayItem 修改为
[XmlArrayItem(elementName: "doubi")]
这时运行可以看到把 dependency 修改为 doubi ,请看代码
<?xml version="1.0" encoding="utf-16"?><metadata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><id>lindexi.MVVM.Framework</id><dependencies><doubi id="lindexi.wpf.Framework" version="[1.1.2,)" /></dependencies></metadata>
这是原来的代码
<dependencies><dependency id="lindexi.wpf.Framework" version="[1.1.2,)" /></dependencies>
修改后的代码
<dependencies><doubi id="lindexi.wpf.Framework" version="[1.1.2,)" /></dependencies>
所有代码
[XmlType(typeName: "metadata")]
public class NuspecMetadata
{
[XmlElement("id")]
public string Id { get; set; }
[XmlArray(elementName: "dependencies")]
public List<NuspecDependency> Dependencies { set; get; } = new List<NuspecDependency>();
}
[XmlType("dependency")]
public class NuspecDependency
{
[XmlAttribute("id")]
public string Id { get; set; }
[XmlAttribute(attributeName: "version")]
public string Version { get; set; }
}
去掉命名空间
默认保存的 xml 的字符串,可以看到如下面的命名空间
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
那么如何去掉xmlns:xsi
命名空间
最简单的方法是创建 XmlSerializerNamespaces
添加空白的命名空间
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
在序列类时传入
xmlSerializer.Serialize(xmlWriter, nuspecMetadata, ns);
所有代码
var nuspecMetadata = new NuspecMetadata()
{
Id = "lindexi.MVVM.Framework",
Dependencies =
{
new NuspecDependency()
{
Id = "lindexi.wpf.Framework",
Version = "[1.1.2,)"
}
}
};
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
var str = new StringBuilder();
using (var xmlWriter = XmlWriter.Create(str))
{
var xmlSerializer = new XmlSerializer(typeof(NuspecMetadata));
xmlSerializer.Serialize(xmlWriter, nuspecMetadata, ns);
}
var rawceeyopereSuwhisa = str.ToString();
Console.WriteLine(rawceeyopereSuwhisa);
[XmlType(typeName: "metadata")]
public class NuspecMetadata
{
[XmlElement("id")]
public string Id { get; set; }
[XmlArray(elementName: "dependencies")]
public List<NuspecDependency> Dependencies { set; get; } = new List<NuspecDependency>();
}
[XmlType("dependency")]
public class NuspecDependency
{
[XmlAttribute("id")]
public string Id { get; set; }
[XmlAttribute(attributeName: "version")]
public string Version { get; set; }
}
尝试运行上面代码
<?xml version="1.0" encoding="utf-16"?><metadata><id>lindexi.MVVM.Framework</id><dependencies><dependency id="lindexi.wpf.Framework" version="[1.1.2,)" /></dependencies></metadata>
找不到文件异常
在保存文件的构造函数 XmlSerializer 如果在 dotnet framework 4.5 以上,那么会出现异常
System.IO.FileNotFoundException
System.IO.FileNotFoundException occurred
Message="Could not load file or assembly '[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified."
Source="mscorlib"
FileName="[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
FusionLog=""
StackTrace:
at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
这是因为垃圾微软会先找程序集的 XmlSerializers ,也就是[xx程序集].XmlSerializers.dll 从这个程序集可能包含如何序列类的代码,这样可以提高性能。如果这个dll 没有生成,那么就会出现这个异常。默认是没有生成这个类。这里出现了异常,没关系,垃圾微软会在构造函数拿到这个异常,在运行时生成序列的代码。
所以只需要不管这个异常就可以
XmlIgnore
这个特性表示类的某个属性需要在序列忽略,也就是不使用这个属性
在 xml 序列忽略某个属性就需要在这个属性设置 [XmlIgnore]
,请看代码
[XmlIgnore]
public string KawbishumaVaslufeeyairrea { get; set; } = "lindexi.github";
参见:
项目文件中的已知 NuGet 属性(使用这些属性,创建 NuGet 包就可以不需要 nuspec 文件啦) - walterlv
将 WPF、UWP 以及其他各种类型的旧样式的 csproj 文件迁移成新样式的 csproj 文件 - walterlv
c# - XmlSerializer giving FileNotFoundException at constructor - Stack Overflow
我搭建了自己的博客 https://lindexi.gitee.io/ 欢迎大家访问,里面有很多新的博客。只有在我看到博客写成熟之后才会放在csdn或博客园,但是一旦发布了就不再更新
如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。
C# 序列类为 xml 可以使用的特性大全的更多相关文章
- 2019-11-29-C#-序列类为-xml-可以使用的特性大全
title author date CreateTime categories C# 序列类为 xml 可以使用的特性大全 lindexi 2019-11-29 8:59:2 +0800 2018-6 ...
- 2018-10-19-C#-序列类为-xml-可以使用的特性大全
title author date CreateTime categories C# 序列类为 xml 可以使用的特性大全 lindexi 2018-10-19 9:9:47 +0800 2018-6 ...
- PythonI/O进阶学习笔记_4.自定义序列类(序列基类继承关系/可切片对象/推导式)
前言: 本文代码基于python3 Content: 1.python中的序列类分类 2. python序列中abc基类继承关系 3. 由list的extend等方法来看序列类的一些特定方法 4. l ...
- 利用JAXB实现java实体类和xml互相转换
1.应用场景 在使用WebService实现数据上传下载,数据查询时,可以利用JAXB实现java实体类和xml互相转换 2.Demo 2.1 student.java 实体类,包含list(set同 ...
- C# 使用XmlDocument类对XML文档进行操作
原创地址:http://www.cnblogs.com/jfzhu/archive/2012/11/19/2778098.html 转载请注明出处 W3C制定了XML DOM标准.很多编程语言中多提供 ...
- c#通用配置文件读写类(xml,ini,json)
.NET下编写程序的时候经常会使用到配置文件.配置文件格式通常有xml.ini.json等几种,操作不同类型配置文件需要使用不同的方法,操作较为麻烦.特别是针对同时应用不同格式配置文件的时候,很容易引 ...
- python的序列类
1,我们常见的数据结构有哪些是序列类 序列类型的分类: ① 容器序列:list,tuple,deque(可以防止任意的类型的容器) ② 扁平序列:str,bytes,bytearray,array ...
- C#实体类与XML相互转换
1.实体类与XML相互转换 将实体类转换成XML需要使用XmlSerializer类的Serialize方法,将实体类序列化. 把XML转换成相应的实体类,需要使用到XmlSerializer类的De ...
- JAXB—Java类与XML文件之间转换
JAXB-Java类与XML文件之间转换 简介 JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生 ...
随机推荐
- Linux 7.X 网络配置
Linux 7.X 网络配置 环境: 笔记本中安装了虚拟机,在虚拟机中安装了Redhat 7.4版本的操作系统,现配置该操作系统网络.(IP.网关等) 相关指令如下: # nmcli connecti ...
- KiCad 元件值 F4NNIU 规范(2019-10-10)
目录 KiCad 元件值 F4NNIU 规范 电阻 电容 电感 二极管 三极管 MOSFET IC 文件历史 KiCad 元件值 F4NNIU 规范 为方便物料统计以及规范物料,在制造 BOM 时可以 ...
- 【滴水石穿】rn
这个项目还不错,还比较全 先放项目地址:https://github.com/ShionHXC/rn 项目算是一个完整的APP 有用到redux-thunk存储数据,算的上是一个普通的比较完整的APP ...
- 【codeforces Manthan, Codefest 17 C】Helga Hufflepuff's Cup
[链接]h在这里写链接 [题意] k是最高级别的分数,最高界别的分数最多只能有x个. 1<=k<=m; 和k相邻的点的分数只能小于k; n个点的树,问你每个 ...
- Codeforces 439C
题目链接 比赛时间没能通过==, 只能说明自己代码写的太不严谨咯! 解题思想就是贪心 先判断无解的情况: 1. 奇数不够,因为偶数是无法凑成奇数的 2. 偶数不够,2个奇数可以凑成一个偶数 3. 在奇 ...
- viewpager实现进入程序之前的欢迎界面效果
用viewpager实现该效果大致需要5步 1,用support.v4包下的ViewPager.xml布局如下: <android.support.v4.view.ViewPager andro ...
- Mongodb停止和启动
mongodb开启.停止.重启操作 #开启service mongodb start#停止service mongodb stop#重启service mongodb restart
- 跟我一起认识axure(一)
第一步下载:https://www.axure.com.cn/ 第二步点击安装,一路next 第三步:认识Axure RP工作界面
- Python学习之路8☞迭代器协议和生成器
一 什么是迭代器协议 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退) 2.可迭代 ...
- 利用IDEA构建springboot应用-Controller的使用
Controller的使用 @Controller 处理http请求 @RestController Spring4之后新加的注解,原来返回json需要@ResponseBody配合@Contr ...