C# .NET Core 5.0 如何通过代码修改Properties.Resources只读属性值

问题原因
Properties.Resources是Visual Studio自动为.resx资源文件生成的强类型包装类,所有资源属性默认仅提供get访问器,且嵌入到程序集中的资源本身是静态不可修改的,因此直接执行Properties.Resources.defaultLanguage = "TEST"赋值不会生效。
方案1:运行时临时覆盖(程序重启后恢复原值)
该方案适合仅需要在当前程序运行周期内生效的场景,共有两种实现方式:
方式A:自定义包装类(更简单易维护)
自己封装一层静态类,优先读取自定义的覆盖值,没有覆盖时读取原生资源:public static class ResourceHelper { private static readonly Dictionary<string, object> _overrideRes = new Dictionary<string, object>(); public static string DefaultLanguage { get { if (_overrideRes.ContainsKey(nameof(DefaultLanguage))) return _overrideRes[nameof(DefaultLanguage)].ToString(); return Properties.Resources.defaultLanguage; } set => _overrideRes[nameof(DefaultLanguage)] = value; } }后续需要读值、赋值都操作
ResourceHelper.DefaultLanguage即可生效。方式B:反射修改资源缓存(修改后直接读原
Properties.Resources即可生效)
通过反射修改ResourceManager内部缓存的资源值,改完后直接读取原生资源属性就会返回新值:// 需要提前引入命名空间:System.Reflection、System.Collections、System.Threading var resManager = Properties.Resources.ResourceManager; // 读取ResourceManager内部缓存的资源集合 var resSets = resManager.GetType() .GetField("_resourceSets", BindingFlags.NonPublic | BindingFlags.Instance) ?.GetValue(resManager) as Hashtable; if (resSets != null && resSets.Contains(Thread.CurrentThread.CurrentUICulture)) { var currentResSet = (ResourceSet)resSets[Thread.CurrentThread.CurrentUICulture]; // 修改当前语言下的资源表对应值 var resTable = (Hashtable)currentResSet.GetType() .GetField("_table", BindingFlags.NonPublic | BindingFlags.Instance) ?.GetValue(currentResSet); if (resTable != null) { resTable["defaultLanguage"] = "TEST"; } }
方案2:永久修改资源文件(修改后下次启动也生效)
如果需要永久修改资源值,需要直接操作.resx源文件,注意:该方案仅适用于.resx文件外置的场景,已经嵌入到程序集的资源无法永久修改。
// 需要提前引入命名空间:System.Resources、System.Collections string resxFilePath = @"你的Resources.resx文件本地路径"; var allRes = new Dictionary<string, object>(); // 读取现有所有资源 using (var resReader = new ResXResourceReader(resxFilePath)) { foreach (DictionaryEntry entry in resReader) { allRes[entry.Key.ToString()] = entry.Value; } } // 修改目标资源值 allRes["defaultLanguage"] = "TEST"; // 重新写入资源文件 using (var resWriter = new ResXResourceWriter(resxFilePath)) { foreach (var kvp in allRes) { resWriter.AddResource(kvp.Key, kvp.Value); } resWriter.Generate(); }
额外建议
如果你的业务场景需要频繁修改该类可配置值,更推荐使用专门的配置文件(如JSON、XML格式配置)存储,而非嵌入资源。嵌入资源更适合存放程序运行过程中不需要修改的静态内容。
内容的提问来源于stack exchange,提问作者Vez
相关产品推荐
相关产品推荐

