Xamarin C#运行时从数据库更新嵌入资源RESX文件方案咨询
嵌入资源RESX无法直接更新,这是可行方案
当RESX被标记为嵌入资源后,它会被编译进程序集(.dll/.exe),运行时程序集是只读的,所以没法直接修改嵌入的RESX内容。下面是几种替代方案:
方案1:内存字典覆盖(推荐,不修改文件)
读取嵌入RESX的内容到内存字典,再用数据库的数据覆盖或新增键值对,后续本地化时直接从这个内存字典取值:
// 初始化ResourceManager读取嵌入资源 var resourceManager = new ResourceManager("YourProjectNamespace.Resources", Assembly.GetExecutingAssembly()); var resourceSet = resourceManager.GetResourceSet(CultureInfo.CurrentUICulture, true, true); // 转成可修改的字典 var resourceDict = resourceSet.Cast<DictionaryEntry>() .ToDictionary(entry => entry.Key.ToString(), entry => entry.Value.ToString()); // 从数据库获取更新数据(自行实现GetUpdatedResourcesFromDb方法) var dbUpdates = GetUpdatedResourcesFromDb(); foreach (var update in dbUpdates) { if (resourceDict.ContainsKey(update.Key)) { resourceDict[update.Key] = update.Value; } else { resourceDict.Add(update.Key, update.Value); } } // 使用时直接从字典取 var localizedContent = resourceDict["WelcomeMessage"];
方案2:将RESX改为非嵌入资源,运行时修改文件
如果必须保留RESX文件形式,把RESX的生成操作改成「内容」,「复制到输出目录」设为「始终复制」,这样文件会被放到输出目录,运行时可以用ResXResourceWriter修改:
// 读取现有RESX文件内容 var resxPath = Path.Combine(AppContext.BaseDirectory, "Resources.resx"); var existingEntries = new List<DictionaryEntry>(); using (var reader = new ResXResourceReader(resxPath)) { existingEntries = reader.Cast<DictionaryEntry>().ToList(); } // 合并数据库更新 var dbUpdates = GetUpdatedResourcesFromDb(); foreach (var update in dbUpdates) { var targetEntry = existingEntries.FirstOrDefault(e => e.Key.ToString() == update.Key); if (targetEntry.Key != null) { targetEntry.Value = update.Value; } else { existingEntries.Add(new DictionaryEntry(update.Key, update.Value)); } } // 写入回RESX文件 using (var writer = new ResXResourceWriter(resxPath)) { foreach (var entry in existingEntries) { writer.AddResource(entry.Key.ToString(), entry.Value.ToString()); } }
注意:这种方式需要程序有文件写入权限,Web应用可能需要重启应用池才能加载新的RESX内容。
方案3:完全用数据库存储本地化资源
放弃RESX,直接把所有本地化键值对存在数据库(比如建表Localization,字段:CultureCode, ResourceKey, ResourceValue),读取时直接查数据库,还可以加内存缓存提升性能:
// 示例:从数据库读取本地化内容 public string GetLocalizedValue(string key, string culture) { // 这里可以加缓存逻辑,避免每次查库 using (var db = new YourDbContext()) { var resource = db.Localization .FirstOrDefault(r => r.ResourceKey == key && r.CultureCode == culture); return resource?.ResourceValue ?? key; // 找不到返回键名作为 fallback } }
内容的提问来源于stack exchange,提问作者Wind_dk
相关产品推荐
相关产品推荐

