.NET(C#):浅谈程序集清单资源和RESX资源
目录
程序集清单资源
在程序集中嵌入资源的最简单方法是什么?那就是使用Visual Studio中的“嵌入式资源(Embedded Resource)”创建选项,相当于使用csc的”/resource”参数。具体步骤,首先在Visual Studio的工程中选择资源文件,然后选择“属性”,接着在属性框中的Build Action中选择Embedded Resource,如下图,把a.file作为资源文件。
这个a.file成为嵌入资源后,它将会作为清单资源(Manifest Resource)存入程序集清单中(Assembly Manifest):
程序集清单是程序集不可缺少的元素,上图来自MSDN,可以参考更多关于程序集或者程序集清单的信息在这里:http://msdn.microsoft.com/zh-cn/library/1w45z383(v=VS.100).aspx,本文就不再多说了。
接下来要关心的是怎样使用程序集清单中的资源。
我们可以使用Assembly类的GetManifestResourceNames方法,返回程序集的所有清单资源的文件名。
或者Assembly.GetMenifestResourceStream方法返回指定资源的流。
比如刚才那个包含a.file的程序集。
var ass = Assembly.GetExecutingAssembly();
foreach(var file in ass.GetManifestResourceNames())
Console.WriteLine(file);
输出
Mgen.a.file
前面的Mgen是程序集的默认命名空间,VS在编译后会自动把命名空间加在文件名的前面的。
接下来使用GetManifestResourceStream来读取文件内容:
var ass = Assembly.GetExecutingAssembly();
var stream = ass.GetManifestResourceStream("Mgen.a.file");
/* 操作Stream对象来读取文件信息 */
RESX资源文件
另外一种创建资源的形式就是RESX资源文件,这个通过VS的添加文件中的“资源文件”类型。RESX文件相比手动创建上面讲的程序集清单资源最大的优势就是:
- 支持多语言
- 快速创建资源
- 管理方便
RESX可以支持多语言,Visual Studio编译后会出现附属程序集(satellite assembly),事实上是连接器(AL.exe)做这份工作。程序在执行在不同语言环境会搜索相应语言的资源。同时Visual Studio还提供了强大的RESX的资源编辑器。
同程序集清单资源一样,我们还是要弄懂所谓RESX资源到底是怎么存的。
现在,在工程中创建一个Resource1.resx,编辑它,添加一个b.file文件,再添加一个字符串,随便写个名称。
完成后,你会发现工程里多了些文件:
a.file是上面我们手动加的程序集清单资源。而Resource1.resx中的文件被存到了一个叫Resources的文件夹内(图中的b.file)。
检查这两个文件的属性中的Build Action,你会发现,Resources内的文件的Build Action都是None,VS不会对他们进行任何操作的,就好像他们不在工程里似的。而RESX文件的Build Action则是Embedded Resource,它会成为程序员清单资源,不同于不同程序集清单资源,RESX在编译时下面的Custom Tool是一个叫ResXFileCodeGenerator的工具:
这个工具会把所有RESX的资源连起来创建成一个二进制文件,VS最后把这个生成的文件最终作为程序集清单资源文件保存到程序集中。这个二进制资源文件的扩展名是.resources。
此时再运行上面讲的Assembly.GetManifestResourceNames方法来枚举程序集清单资源文件,输出会成:
Mgen.a.file
Mgen.Resource1.resources
Resource1.resx文件会最终编译成Mgen.Resource1.resources资源文件。
整个过程可以看这张图:
使用ResourceReader和ResourceSet解析二进制资源文件
建议先读这篇文章来先了解IResourceReader,IResourceWriter和ResourceSet类型:.NET(C#):使用IResourceReader,IResourceWriter和ResourceSet。这里就不在讲这三个类型的使用。
上面讲过,RESX资源文件最终会被编译成.resources扩展名的资源文件(二进制)并保存在程序集清单资源(assembly manifest resource)。
下面我们用.NET中的.resources二进制资源文件的解析类ResourceReader和ResourceSet来手动解析这个.resources文件。
代码:
//+ using System.Resources
static void Main()
{
using (Stream resources = Assembly.GetExecutingAssembly().GetManifestResourceStream("Mgen.Resource1.resources"))
{
//使用IResourceReader
ReadUsingResourceReader(resources);
//重新定位Stream
, SeekOrigin.Begin);
//使用ResourceSet
ReadUsingResourceSet(resources);
}
}
//使用IResourceReader
static void ReadUsingResourceReader(Stream st)
{
Console.WriteLine("== 使用IResourceReader");
IResourceReader rr = new ResourceReader(st);
var iter = rr.GetEnumerator();
while (iter.MoveNext())
Console.WriteLine("键: {0} 值: {1}", iter.Key, iter.Value);
//不需要调用IResourceReader.Dispose,Stream会在Main方法中被Dipose
}
//使用ResourceSet
static void ReadUsingResourceSet(Stream st)
{
Console.WriteLine("== 使用ResourceSet");
ResourceSet rs = new ResourceSet(new ResourceReader(st));
Console.WriteLine(BitConverter.ToString((byte[])rs.GetObject("b")));
Console.WriteLine(rs.GetString("String1"));
//不需要调用ResourceSet.Dispose,Stream会在Main方法中被Dipose
}
这将会以ResourceReader和ResourceSet两种方式输出b.file的字节内容和String1字符串。
使用ResourceManager解析二进制资源文件
关于ResourceManager类型的使用,可以参考:.NET(C#):使用ResourceManager类型。这里就不再多讲了。
我们就直接使用ResourceManager,还是上面的工程,用ResourceManager来解析这个.resources二进制的资源文件。
代码:
//+ using System.Resources
ResourceManager resManager = new ResourceManager(typeof(Resource1));
//等效于:new ResourceManager("Mgen.Resource1", Assembly.GetExecutingAssembly());
//此时ResourceManager.BaseName是Type.FullName正好是Mgen.Resource1
//获取file.b的内容
Console.WriteLine(BitConverter.ToString((byte[])resManager.GetObject("b")));
//获取资源中的字符串
Console.WriteLine(resManager.GetString("String1"));
这将会输出b.file的字节内容和String1字符串。
小看RESX资源文件的Designer.cs文件
最后再让我们看看RESX资源文件后面的那个xxx.Designer.cs文件。
它定义了资源读取的一个类,比如资源文件名称是Resource1,这个类的名称就是Resource1。这个类其实就是内部包装了一个上面讲的ResourceManager,并且根据用户RESX定义的资源数据显示的定义具有强类型的属性值用来读取文件。
其内部ResourceManager是这样被初始化的,可以看到,ResourceManager.BaseName就是程序集清单资源的名称(注意ResourceManager.BaseName属性没有CultureInfo名称和.resources扩展名,但是有命名空间(其实完全就是文件名),所以本例中的Mgen.Resource1.resources程序集清单资源文件的ResourceManager初始化BaseName就是:Mgen.Resource1。)
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Mgen.Resource1", typeof(Resource1).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
接着RESX中定义的文件b和字符串String1资源完全就是ResourceManager的方法的包装,比如b文件读取返回字节数组,就是调用ResourceManager.GetObject,然后转换成byte[]:
internal static byte[] b {
get {
object obj = ResourceManager.GetObject("b", resourceCulture);
return ((byte[])(obj));
}
}
好了,就到这里吧,希望读者读完文章后对RESX文件和程序集清单资源有更好的理解!
.NET(C#):浅谈程序集清单资源和RESX资源的更多相关文章
- 【转】.NET(C#):浅谈程序集清单资源和RESX资源 关于单元测试的思考--Asp.Net Core单元测试最佳实践 封装自己的dapper lambda扩展-设计篇 编写自己的dapper lambda扩展-使用篇 正确理解CAP定理 Quartz.NET的使用(附源码) 整理自己的.net工具库 GC的前世与今生 Visual Studio Package 插件开发之自动生
[转].NET(C#):浅谈程序集清单资源和RESX资源 目录 程序集清单资源 RESX资源文件 使用ResourceReader和ResourceSet解析二进制资源文件 使用ResourceM ...
- 浅谈Android样式开发之selector
引言 上一篇Android UI中文章我们详细介绍了Android中shape标签的使用.通过shape标签我们可以定义矩形.椭圆.环形.直线等效果.不过shape只能定义单一的形状,在实际开发中,我 ...
- iOS开发之浅谈MVVM的架构设计与团队协作
今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...
- 浅谈iOS中MVVM的架构设计与团队协作
说到架构设计和团队协作,这个对App的开发还是比较重要的.即使作为一个专业的搬砖者,前提是你这砖搬完放在哪?不只是Code有框架,其他的东西都是有框架的,比如桥梁等等神马的~在这儿就不往外扯了.一个好 ...
- IOS中 浅谈iOS中MVVM的架构设计与团队协作
今天写这篇文章是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇文章的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...
- 浅谈iOS中MVVM的架构设计与团队协作【转载】
今天写这篇文章是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇文章的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...
- 浅谈html5网页内嵌视频
更好的阅读体验:浅谈html5网页内嵌视频 如今在这个特殊的时代下:flash将死未死,微软和IE的历史问题,html5标准未定,苹果和谷歌的闭源和开源之争,移动互联网的大势所趋,浏览器各自为战... ...
- 浅谈ImageList
ImageList组件用了很久,但是一直不太清楚它的实现原理,今天专门特意花了时间倒腾了下,终于弄明白了!于是在这里和大家分享下! 在设计页面中打卡工具箱-组件 找到ImageList组件,将它直接拖 ...
- 浅谈程序员创业(要有一个自己的网站,最好的方式还是自己定位一个产品,用心把这个产品做好。或者满足不同需求的用户,要有特色)good
浅谈程序员创业 ——作者:邓学彬.Jiesoft 1.什么是创业? 关于“创业”二字有必要重新学习一下,找了两个相对权威定义: 创业就是创业者对自己拥有的资源或通过努力能够拥有的资源进行优化整合,从而 ...
随机推荐
- [HTML5游戏开发]简单的《找没有同汉字版〗爆去考考您狄综力吧
[color=ize:18px]一,筹办工做 本次 游戏开发需求用到lufylegend.js开源游戏引擎,版本我用的是1.5.2(如今最新的版本是1.6.0). 引擎下载的位置:http: ...
- 445port入侵详细解释
445port入侵具体解释 关于"445port入侵"的内容445port入侵具体解释本站搜索很多其它关于"445port入侵"的内容 445port入侵, ...
- IntelliJ IDEA常见问题解决办法汇总
(1)SVN相关的操作: 启用:方法1:VCS菜单下Enable Version Control Integration,点击之后选择相应的版本控制工具方法2:Setting中Version Cont ...
- Android规范发展
一.Android 编码规范 1.java 代码中不出现中文.最多凝视中能够出现中文 2.局部变量命名.静态成员变量命名 仅仅能包括字母,单词首字母出第一个外,都为大写,其它字母都为小写 3.常量命名 ...
- 活动图(Activity Diagram) - 项目分解文章
案例基础上登录用户进行操作的每个模块. 1. 员 (1) 列车顺序表 (2) 货车装卸报告(数据处理) (3) 货车装卸报告(查看) 2. 管理员 (1) password管理 (2) 查看日志 (3 ...
- enumerateObjectsUsingBlock、enumerateObjectsWithOptions、enumerateObjectsAtIndexes、makeObjectsPerfor使用
OC至 NSArray它提供了一个方便的遍历block,以下具体说明 第一.enumerateObjectsUsingBlock NSArray *array=@[@"aa",@& ...
- Codeforces Round #223 (Div. 2)--A. Sereja and Dima
Sereja and Dima time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...
- 使用 Gradle 插件进行代码分析(转)
代码分析在大多数项目中通常是作为最后一个步骤(如果做了的话)完成的.其通常难以配置及与现有代码整合. 本文旨在勾勒出使用 Gradle 整合 PMD 与 FindBugs 的步骤,并将其与一个现有的 ...
- JAVA环境配置---------jdk安装路径中存在空格的问题
我把jdk 安装在C:\Program Files下 而ide启动脚本 startup.bat 例如以下: if "%OS%"=="Windows_NT" se ...
- ios 动态设置Cell高低
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPa ...