ResourceManager.GetString返回null,动态调用resx中SQL脚本失败
动态调用resx中SQL脚本资源的解决方案
看起来你已经通过手动调用静态属性验证了资源是正常的,问题出在动态调用的方式不对。我来帮你修正这两种方案,再给你更可靠的实现思路:
问题分析
先拆解你之前的错误点:
- ResourceManager返回null:大概率是因为没有指定正确的文化(Culture),或者资源名称的大小写/格式不匹配;
- 反射InvokeMember报错:你用了
BindingFlags.Instance,但Designer.cs里生成的属性是**静态(static)**的,而且你用了SetProperty(设置属性),但我们需要的是GetProperty(读取属性),这两个错误直接导致找不到目标成员。
解决方案一:修正反射调用(推荐)
直接通过反射获取静态属性的值,和你手动调用的逻辑完全一致,可靠性更高:
for (int i = DbVersion + 1; i <= FileDbVersion; i++) { string updateScripts = "script_" + i.ToString("D5"); // 获取静态属性 var prop = typeof(SQLUpdateScripts).GetProperty( updateScripts, BindingFlags.Static | BindingFlags.Public // 注意是静态+公共属性 ); if (prop == null) { // 处理找不到脚本的情况,比如日志记录 continue; } // 静态属性不需要实例,传null即可 string myString = (string)prop.GetValue(null); var sqlqueries = myString.Split(new[] { "\nGO", "\ngo" }, StringSplitOptions.RemoveEmptyEntries); // 执行你的SQL脚本逻辑... }
如果你坚持用InvokeMember,也可以调整为正确的写法:
string myString = (string)typeof(SQLUpdateScripts).InvokeMember( updateScripts, BindingFlags.Static | BindingFlags.Public | BindingFlags.GetProperty, Type.DefaultBinder, null, // 静态成员不需要实例 null );
解决方案二:修复ResourceManager调用
如果想用ResourceManager,需要确保指定不变文化(InvariantCulture),避免因当前线程文化差异导致找不到资源:
using System.Globalization; // ... for (int i = DbVersion + 1; i <= FileDbVersion; i++) { string updateScripts = "script_" + i.ToString("D5"); ResourceManager sqLUpdateScripts = new ResourceManager(typeof(SQLUpdateScripts)); // 明确指定InvariantCulture,匹配资源的默认文化 string myString = sqLUpdateScripts.GetString(updateScripts, CultureInfo.InvariantCulture); if (string.IsNullOrEmpty(myString)) { // 处理资源不存在的情况 continue; } var sqlqueries = myString.Split(new[] { "\nGO", "\ngo" }, StringSplitOptions.RemoveEmptyEntries); // 执行脚本逻辑... }
额外检查项
- 确认resx文件中资源的名称完全匹配
script_00001格式(C#属性名区分大小写,注意拼写和大小写一致); - 检查resx文件的访问修饰符:如果是
internal,确保你的调用代码和SQLUpdateScripts类在同一个程序集里; - 验证
i.ToString("D5")生成的是5位数字(比如1变成00001),和resx里的资源名称完全对应。
内容的提问来源于stack exchange,提问作者rippergr
相关产品推荐
相关产品推荐

