2018-10-19-C#-序列类为-xml-可以使用的特性大全
| title | author | date | CreateTime | categories |
|---|---|---|---|---|
|
C# 序列类为 xml 可以使用的特性大全
|
lindexi
|
2018-10-19 9:9:47 +0800
|
2018-6-23 9:36:2 +0800
|
C#
|
本文告诉大家如何使用序列类,以及序列时可以用到的特性,特性的作用和一些容易被问的问题
最近我在把项目文件修改为 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
2018-10-19-C#-序列类为-xml-可以使用的特性大全的更多相关文章
- C# 序列类为 xml 可以使用的特性大全
本文告诉大家如何使用序列类,以及序列时可以用到的特性,特性的作用和一些容易被问的问题 最近我在把项目文件修改为 VisualStudio 2017 的格式,请看从以前的项目格式迁移到 VS2017 新 ...
- 20172319 2018.10.19《Java程序设计教程》第7周课堂实践(补写博客)
20172319 2018.10.19 <Java程序设计教程>第7周课堂实践 课程:<程序设计与数据结构> 班级:1723 学生:唐才铭 学号:20172319 指导老师:王 ...
- IDC Digital Transition Annual Festival(2018.10.19)
时间:2018.10.19地点:北京万达文化酒店
- 2018.10.19浪在ACM 集训队第一次测试赛
2018.10.19浪在ACM 集训队第一次测试赛 待参考资料: [1]:https://blog.csdn.net/XLno_name/article/details/78559973?utm_so ...
- 2018.10.19 NOIP训练 变化的序列(线性dp)
传送门 f[i][j]f[i][j]f[i][j]表示后iii个对答案贡献有jjj个a的方案数. 可以发现最后a,ba,ba,b的总个数一定是n∗(n−1)/2n*(n-1)/2n∗(n−1)/2 因 ...
- 2018.10.19 bzoj1057: [ZJOI2007]棋盘制作(悬线法)
传送门 悬线法板题. 如果只求最大矩形面积那么跟玉蟾宫是一道题. 现在要求最大正方形面积. 所以每次更新最大矩形面积时用矩形宽的平方更新一下正方形答案就行了. 代码: #include<bits ...
- 2018.10.19 NOIP训练 桌子(快速幂优化dp)
传送门 勉强算一道dp好题. 显然第kkk列和第k+nk+nk+n列放的棋子数是相同的. 因此只需要统计出前nnn列的选法数. 对于前mmm%nnn列,一共有(m−1)/n+1(m-1)/n+1(m− ...
- 2018.10.19 bzoj1584: Cleaning Up 打扫卫生(线性dp)
传送门 dp妙题. 考虑到每个位置分一组才花费nnn的贡献. 因此某一段不同的数的个数不能超过sqrt(n)sqrt(n)sqrt(n),于是对于当前的位置iii我们记pos[j]pos[j]pos[ ...
- 2018.10.19 NOIP模拟 比特战争(kruskal)
传送门 考完发现是sbsbsb题啊. 直接考虑优化状压的转移. 可以证明最优解一定在求最小生成树的时候取得. 因此再最小生成树时维护一下连通块的最值统计答案就行了. 代码
- 2018.10.19 NOIP模拟 硬币(矩阵快速幂优化dp)
传送门 不得不说神仙出题人DZYODZYODZYO出的题是真的妙. f[i][j][k]f[i][j][k]f[i][j][k]表示选的硬币最大面值为iii最小面值不小于jjj,总面值为kkk时的选法 ...
随机推荐
- 使用Echarts的步骤
Echarts官网地址:https://echarts.baidu.com/index.html 步骤如下: 1.获取Echarts (1)可以在Echarts官网去下载,选择需要的版本下载,根据开发 ...
- thinkphp Trace方法
页面Trace只能用于有页面输出的情况,但是trace方法可以用在任何情况,而且trace方法可以用于AJAX等操作. Trace方法的格式: trace('变量','标签','级别','是否记录日志 ...
- 新金融ABS如何做?听听这几十家券商、互金高管的经验之谈
新金融ABS如何做?听听这几十家券商.互金高管的经验之谈 2016-11-24 零壹财经 ID:36104743 时间:2016年11月初 地点:北京东城区南湾子3号院(场地提供方:无讼.天同律师事务 ...
- MyBatis基础-CRUD
一.mybatis 环境搭建步骤 第一步:创建 maven 工程第二步:导入坐标第三步:编写必要代码(实体类和持久层接口)第四步:编写 SqlMapConfig.xml第五步:编写映射配置文件第六步 ...
- java读取字符串,生成txt文件
/** * 读取字符串,生成txt 文件 已解决未设置编码时,在项目中直接打开文件,中文乱码问题 * WriteText.writeToText(musicInfo,fileName)直接调用 * * ...
- 9个永恒的UI设计原则
很多人都在寻找那些能够帮助他们快速提升设计能力的方法,但你是否想过,自己身上的哪些方面会对你的设计产生影响呢?是使用工具的技巧,对设计的理解和态度,还是你的生活习惯呢?我想说所有这些都是决定你的设计是 ...
- Java工具类NumberUtils使用
int数据类型和long数据类型 int占32位,long占64位,long表示的数据更大:public static int toInt(String str) NumberUtils.toInt( ...
- Oracle如何用单字段或多字段进行查重
最近在整理数据形成信用报告,发现重复的数据真的多,梳理都好久.我就做个笔记把去掉重复数据的方法整理下来.方便我后期查阅. 我将我目前已知的两种去重方法分为:视图去重和表去重.原理就是有无rowid这个 ...
- 关于Button控件的CommandName属性用法的一个实例
注:本文分享于悠闲的博客,地址:http://www.cnblogs.com/9999/archive/2009/11/24/1609234.html 1.前台的代码 <%@ Page Lang ...
- T2960 全民健身【思维Dp,预处理,差分优化】
Online Judge:YCJSOI Label:Dp,思维题,预处理,滚动优化 题目描述 乐乐现在掌管一个大公司,办公楼共有n层.为了增加员工的身体素质,他决定在每层楼都建立一个活动室,活动室分乒 ...