技术开发 频道

C#:浅谈程序集清单资源和RESX资源

  使用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
                resources.Seek(
0, 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。)

        //+ using System.Resources
        static void Main()
        {
            using (Stream resources
= Assembly.GetExecutingAssembly().GetManifestResourceStream("Mgen.Resource1.resources"))
            {
                
//使用IResourceReader
                ReadUsingResourceReader(resources);
                
//重新定位Stream
                resources.Seek(
0, 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
        }

   接着RESX中定义的文件b和字符串String1资源完全就是ResourceManager的方法的包装,比如b文件读取返回字节数组,就是调用ResourceManager.GetObject,然后转换成byte[]:

        internal static byte[] b {
            get {
                object obj
= ResourceManager.GetObject("b", resourceCulture);
                
return ((byte[])(obj));
            }
        }

   好了,就到这里吧,希望读者读完文章后对RESX文件和程序集清单资源有更好的理解!

  原文链接:http://www.cnblogs.com/mgen/archive/2011/12/11/2283917.html

1
相关文章