C# 读取嵌入项目中的资源文件

目标:读取嵌入项目中的文件资源。
工具: VS2019 community
有时候,我们需要使用定义的标准模板文件作为基准,对程序进行相应的设置,但是模板文件如果作为明文文件放置在应用程序的路径下,可能会被外边界的其它因素修改。这时候就需要把文件作为资源嵌入到项目的应用程序,或者dll库中。这里介绍使用内嵌入应用程序的方法。
把项目文件资源嵌入应用程序中,有2中方法可以实现:
一。把项目使用的资源文件统一放置在一个自定义文件夹中

  1. 把项目使用的资源文件统一放置在一个自定义文件夹中,并设置为嵌入资源。如下图
    C# 读取嵌入项目中的资源文件_第1张图片
    黄色框内是新建的一个文件夹,名称为InsertedFiles,然后我们添加一个文件,名称为system.ini。把文件的生成操作设置为“嵌入的资源”,如红色框内所示。
    我们后续读取该文件时,需要使用的路径为:项目名称.文件夹.文件名称。比如这里的项目名称是MacroProgram,则我们要读取的文件具体路径就是:MacroProgram.InsertedFiles.system.ini
  2. 读取文件的C#代码如下:
		/// 
        /// 从项目嵌入的资源中读取指定的资源文件。
        /// 
        /// 指定的资源文件名称
        /// 返回的资源文件流
        public Stream GetResource(string filename)
        {
            filename = "InsertedFiles.system.ini";
            //获得正在运行类所在的名称空间          
            string _namespace = MethodBase.GetCurrentMethod().DeclaringType.Namespace;
            
            //获得当前运行的Assembly 方法1  
            Assembly _assembly = Assembly.GetExecutingAssembly(); 
            //获得当前运行的Assembly 方法2
            Assembly _assembly1 = this.GetType().Assembly;
            //读取assembly的名称
            _namespace = _assembly.GetName().Name;
            //根据名称空间和文件名生成资源名称
            string resourceName = _namespace+"." + filename;
            Debug.Print(_namespace +":"+resourceName);
            //根据资源名称从Assembly中获取此资源的Stream
            Stream istr = _assembly.GetManifestResourceStream(resourceName);
#if DEBUG
            if (istr is null) Debug.Print(resourceName+" is NULL");
            else Debug.Print(resourceName +" is OK");
#endif          
#if DEBUG          
            // Enumerate the assembly's manifest resources
            foreach (string resourceName1 in _assembly.GetManifestResourceNames())
            {
                Debug.Print(resourceName1);
                istr = _assembly.GetManifestResourceStream(resourceName1);

                if (istr is null) Debug.Print(resourceName1 +" is not found");
                else Debug.Print(resourceName1+" is Found");

            }
#endif
            return istr;
        }
  1. 运行后得到的输出如下:参见红色框内结果:
    C# 读取嵌入项目中的资源文件_第2张图片
    第一个红框是读取的结果输出,第二个是读取当前项目中所有资源的结果,说明我们嵌入到 项目中的文件在整体资源中。

二。把资源文件嵌入到项目的资源中。
(暂时发布,明天继续)
continue:
这是最省事的方法,没有之一。因为微软已经帮忙做好了很多准备。在项目属性的资源里面添加对应得文件资源后,就可以直接使用Properties.Resources进行资源调用了;当然,也可以是用内嵌的ResourceManager来调用资源文件。参见下图:
C# 读取嵌入项目中的资源文件_第3张图片
我们插入图片About.gif后,会得到1框的资源列表,这个资源不管是嵌入的资源,还是其它模式的资源,都可以使用Properties.Resources.About来进行调用,此时注意,这是按照资源属性来调用资源的,没有文件的扩展名。其实这个调用微软已经进行后台处理了,参见下段代码:

 /// 
        ///   查找 System.Drawing.Bitmap 类型的本地化资源。
        /// 
        public static System.Drawing.Bitmap About {
            get {
                object obj = ResourceManager.GetObject("About", resourceCulture);
                return ((System.Drawing.Bitmap)(obj));
            }
        }

这段代码是系统自动生成的,也展示了如何进行调用。也就是说,若想定义自己的调用方法,则可以使用这个ResourceManager.GetObject的方法来调用任何内置的资源,而不使用Properties.Resources进行固定调用。ResourceManager的实例化,微软也已经帮忙内置处理完毕,参见红框2的自动生成代码,也摘录如下:

         /// 
        ///   返回此类使用的缓存的 ResourceManager 实例。
        /// 
        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
        public static global::System.Resources.ResourceManager ResourceManager {
            get {
                if (object.ReferenceEquals(resourceMan, null)) {
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MacroProgram.Properties.Resources", typeof(Resources).Assembly);
                    resourceMan = temp;
                }
                return resourceMan;
            }
        }

然后我们就可以使用这个ResourceManager 进行自己的资源调用,再也不担心资源被他人修改了。这里贴上一个调用代码,只要求实现功能,不求精简:

/// 
        /// 从项目嵌入的项目属性资源中读取指定的资源文件。eg: About.gif
        /// 
        /// 指定的资源文件名称,不带扩展名
        /// 返回的资源对象
        public Object GetPropertiesResources(string filenameOnly)
        {
            //filename = "Resources.About.gif";
            //获得正在运行类所在的名称空间          
            string _namespace = MethodBase.GetCurrentMethod().DeclaringType.Namespace;

            //获得当前运行的Assembly 方法1  
            Assembly _assembly = Assembly.GetExecutingAssembly();
            //获得当前运行的Assembly 方法2
            Assembly _assembly1 = this.GetType().Assembly;
            //读取assembly的名称
            _namespace = _assembly.GetName().Name;
            //根据名称空间和文件名生成资源名称
            string resourceName = _namespace + "" + ".Properties.Resources";
            Debug.Print(_namespace + ":" + resourceName);
            //实例化资源管理类
            ResourceManager resourceManager = new ResourceManager(resourceName, _assembly1);
            //根据资源名获得资源对象
            return resourceManager.GetObject(filenameOnly);
        }

综上两种资源调用,本质是一样的,只是后者已经封装完毕,使用更加方便。
资源已经有了,后续如何流化,如何使用,就根据需要进行处理即可。
完毕。

向兢兢业业的小白同道致意!共勉

你可能感兴趣的:(日常应用,应用C#和爬虫Python,c#,开发语言,后端)