27程序集资源

程序集资源可以看作是Dictionary<string,byte[]>的字节数组。可以将资源直接嵌入到程序集中;也可以将资源单独嵌入到一个程序集,然后由主程序集引用包含资源的程序集,包含资源的程序集也叫卫星程序集(Satellite Assembly)。一个运用场景是:当开发多语言版本应用程序时,把不同的语言包作为资源签入到各个卫星程序集中,供主程序集调用。

 

  通过VS可视化界面把资源嵌入到程序集,并浏览资源文件

在VS下创建Images/1.jpg→右键1.jpg→属性→生成操作的值设置为"签入的资源"
1

 

通过Assembly的实例方法获取资源名称:

        static void Main(string[] args)
        {
            ShowResources();
            Console.ReadKey();
        }
 
        private static void ShowResources()
        {
            Assembly asm = Assembly.GetExecutingAssembly();
            string[] nameArray = asm.GetManifestResourceNames();
            foreach (string name in nameArray)
            {
                Console.WriteLine(name);
                using (Stream s = asm.GetManifestResourceStream(name))
                {
                    Console.WriteLine("资源字节流的长度为:{0}",s.Length);
                }
            }
        }

结果:
2

 

  通过C#编译器将资源嵌入到程序集,并浏览资源文件

→把上面的Program.cs和1.jpg复制到F:\m文件夹下。

→打开"开发人员命令提示",输入:
3

结果:
4

 

  通过在VS中创建.resx文件把资源嵌入到程序集

→在VS项目下创建Resource1.resx文件,输入资源:
10

→把Resource1.resx和2.jpg一同复制到F:\m文件夹中。  

→使用resgen.exe工具,根据Resource1.resx生成后缀为.resources的资源文件(这个才是真正的资源文件,包含了二进制内容)
5
生成完后,在F:\m文件夹中多了Resource1.resources资源文件

→写一段主程序Program1.cs来浏览Resource1.resources资源文件

using System;
using System.Reflection;
using System.IO;
 
class Program1{
    static void Main(string[] args){
        Assembly asm = Assembly.GetExecutingAssembly();
        string[] nameArray = asm.GetManifestResourceNames();
        foreach(string name in nameArray){
            Console.WriteLine(name);
            using(Stream s = asm.GetManifestResourceStream(name)){
                StreamReader reader = new StreamReader(s);
                string text = reader.ReadToEnd();
                if(text.Length > 1000) text = text.Substring(0,1000);
                Console.WriteLine(text);
                Console.ReadKey();
            }
        }
    }
}
 

→把Resource1.resources资源文件嵌入到程序集,生成Program1.exe

6
生成完后,在F:\m文件夹中多了Program1.exe文件

→运行Program1.exe

7
可见,Resource1.resources资源文件的内容的确是二进制的。

→把可视化Resource1.resx文件签入到程序集,生成Program1.exe

8
生成完后,在F:\m文件夹中Program1.exe文件进行了更新

→再次运行Program1.exe

9

可见,在VS中创建的可视化Resource1.resx和通过resgen.exe工具生成的Resource1.resources是有本质区别的,前者是xml文件,后者的内容是二进制。

 

  通过反射获取后缀为.resources的资源文件信息

→主程序中通过ResourceManager来获取资源信息

using System;
using System.Reflection;
using System.IO;
using System.Resources;
using System.Drawing;
 
class Program1{
    static void Main(string[] args){
        ResourceManager r = new ResourceManager("Resource1", Assembly.GetExecutingAssembly());
        string address = r.GetString("address");
        Console.WriteLine("address:" + address);
        Console.ReadKey();
    }
}
 

→输入命令

11
生成完后,在F:\m文件夹中Program1.exe文件进行了更新

→再次运行Program1.exe

12

 

  把资源嵌入到独立程序集中,让主程序来调用

→输入命令,把Resource1.resources资源文件签入到res.dll程序集中

13
生成完后,在F:\m文件夹中多了res.dll程序集文件

→主程序中引用res.dll程序集

using System;
using System.Reflection;
using System.IO;
using System.Resources;
using System.Drawing;
 
class Program1{
    static void Main(string[] args){
        Assembly asm = Assembly.Load("res");
        ResourceManager r = new ResourceManager("Resource1", asm);
        string address = r.GetString("address");
        Console.WriteLine("address:" + address);
        Console.ReadKey();
    }
}
 

→输入命令

14

→再次运行Program1.exe

12

 

  开发多语言版本应用程序

→创建Resource.en.resx文件

15

→重新生成项目,在bin\debug下多了en文件夹

16

→主程序区域性设置为en

            Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en");
            ResourceManager r = new ResourceManager("ConsoleApplication25.Resource",Assembly.GetExecutingAssembly());
            string address = r.GetString("address");
            Console.WriteLine("address:" + address);
            Console.ReadKey();

结果:
17

→把设置区域性en注释掉,默认是中文

            ResourceManager r = new ResourceManager("ConsoleApplication25.Resource",Assembly.GetExecutingAssembly());
            string address = r.GetString("address");
            Console.WriteLine("address:" + address);
            Console.ReadKey();

结果:
12

 

  总结

为什么需要把资源嵌入到程序集?
● 当设计多语言版本的应用程序,可以根据各个国家语言生成对应的资源文件。
● 当资源文件比较大时,把资源文件嵌入到卫星程序集,可以大大减少主程序集的负担。

 

把资源嵌入到程序集或卫星程序集有几种方式:
1、通过资源文件属性设置
2、通过C#编译器
3、通过.resx资源文件    

 

VS可视化界面中的.resx资源文件和最终生成的.resources资源文件是有区别的:
前者的内容是xml文件。
后者的内容是二进制文件。

 

参考资料:
《.NET之美》--张子阳,感谢写了这么好的书!

posted @ 2014-04-08 01:14  Darren Ji  阅读(398)  评论(0编辑  收藏  举报

我的公众号:新语新世界,欢迎关注。