调试模式下如何向VB.NET的My.Resources中添加文件?
可行性分析与解决思路
首先明确:无法在调试运行时直接修改My.Resources静态类。因为My.Resources是编译时从项目的.resx文件生成的只读静态类,运行时程序集已加载,无法动态修改嵌入的资源或静态类结构。但可以通过以下几种方案实现近似需求的自动化:
思路1:调试时自动修改项目的.resx文件,配合VS自动重载
My.Resources的底层是项目中的Resources.resx文件,只要修改这个文件,下次编译时就会同步到My.Resources中。可以在调试退出前,通过代码修改该文件添加资源:
步骤:
- 获取项目根目录下
Resources.resx的物理路径(注意不要取输出目录下的副本,要取项目源码中的文件) - 使用XML操作或
System.Resources命名空间下的类修改.resx,添加文件资源条目 - 配置VS在文件变更时自动重载项目(路径:工具->选项->环境->文档->勾选“检测到文件更改时自动加载”)
- 获取项目根目录下
VB.NET示例代码:
' 假设生成的文件路径为 generatedFilePath,项目resx路径为 resxFilePath Dim resxDoc As New Xml.XmlDocument() resxDoc.Load(resxFilePath) ' 创建资源节点 Dim dataNode As Xml.XmlNode = resxDoc.CreateElement("data") Dim nameAttr As Xml.XmlAttribute = resxDoc.CreateAttribute("name") nameAttr.Value = "GeneratedReport" ' 自定义资源名称 dataNode.Attributes.Append(nameAttr) ' 设置资源类型(二进制文件用字节数组类型) Dim typeAttr As Xml.XmlAttribute = resxDoc.CreateAttribute("type") typeAttr.Value = "System.Byte[], mscorlib" dataNode.Attributes.Append(typeAttr) ' 读取文件并转为Base64写入resx Dim fileBytes As Byte() = IO.File.ReadAllBytes(generatedFilePath) Dim valueNode As Xml.XmlNode = resxDoc.CreateElement("value") valueNode.InnerText = Convert.ToBase64String(fileBytes) dataNode.AppendChild(valueNode) ' 写入resx文件 resxDoc.DocumentElement.AppendChild(dataNode) resxDoc.Save(resxFilePath)
思路2:调试时用临时目录存文件,调试后自动同步到.resx
如果不想在调试运行中修改.resx文件,可以先把生成的文件存到项目内的临时目录,再通过调试后事件自动同步:
- 步骤:
- 调试时,代码将生成的文件写入项目目录下的
DebugResources文件夹 - 编写PowerShell或VB.NET控制台脚本,遍历该文件夹,自动将文件添加到
Resources.resx - 将脚本设置为项目的调试后事件(项目属性->生成事件->调试后事件命令行),调试结束后自动执行同步
- 调试时,代码将生成的文件写入项目目录下的
思路3:自定义动态资源管理类,兼顾调试与发布
自己实现一个资源管理类,调试模式下同时更新.resx文件和运行时临时缓存,发布模式下直接使用My.Resources:
Public Class DynamicResourceManager Private Shared _tempDebugResources As New Dictionary(Of String, Byte()) Public Shared Sub AddDebugResource(resourceName As String, filePath As String) #If DEBUG Then ' 更新项目resx文件(复用思路1的UpdateResxFile方法) UpdateResxFile(resourceName, filePath) ' 临时缓存,供当前调试会话直接使用 _tempDebugResources(resourceName) = IO.File.ReadAllBytes(filePath) #End If End Sub Public Shared Function GetResource(resourceName As String) As Byte() #If DEBUG Then If _tempDebugResources.ContainsKey(resourceName) Then Return _tempDebugResources(resourceName) End If #End If ' 发布模式直接用My.Resources Return TryCast(My.Resources.ResourceManager.GetObject(resourceName), Byte()) End Function Private Shared Sub UpdateResxFile(resourceName As String, filePath As String) ' 实现思路1中的resx修改逻辑 End Sub End Class
内容的提问来源于stack exchange,提问作者Gary Corbell
相关产品推荐
相关产品推荐

