You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C# ASP.NET MVC中根据内部标志重写ResourceManager的GetString方法

解决方案

方案1:自定义ResourceManager子类+反射替换(零视图代码修改)

这个方案不需要改动任何现有视图或业务代码,通过替换默认的ResourceManager实例来实现字符串补丁,是侵入性最低的方式。

实现步骤:

  1. 创建自定义的PatchedResourceManager类,继承自ResourceManager,重写GetString方法添加替换逻辑:
public class PatchedResourceManager : ResourceManager
{
    private readonly string _targetAnimal;

    public PatchedResourceManager(Type resourceSource, string targetAnimal) : base(resourceSource)
    {
        _targetAnimal = targetAnimal;
    }

    public override string GetString(string name) => PatchString(base.GetString(name));
    public override string GetString(string name, CultureInfo culture) => PatchString(base.GetString(name, culture), culture);

    private string PatchString(string original, CultureInfo culture = null)
    {
        if (string.IsNullOrEmpty(original)) return original;
        culture ??= Thread.CurrentThread.CurrentUICulture;

        // 根据当前语言和目标动物做针对性替换
        return culture.Name switch
        {
            "en-US" => ReplaceEnglishTerms(original),
            "zh-CN" => ReplaceChineseTerms(original),
            // 扩展其他语言的替换规则
            _ => original
        };
    }

    private string ReplaceEnglishTerms(string original)
    {
        var lowerAnimal = _targetAnimal.ToLower();
        var pluralAnimal = $"{_targetAnimal}s";
        return original.Replace("dog", lowerAnimal)
                      .Replace("Dog", _targetAnimal)
                      .Replace("dogs", pluralAnimal);
    }

    private string ReplaceChineseTerms(string original)
    {
        var chineseAnimal = _targetAnimal switch
        {
            "Cat" => "猫咪",
            "Squirrel" => "松鼠",
            "Dog" => "狗狗",
            _ => _targetAnimal
        };
        return original.Replace("狗狗", chineseAnimal);
    }
}
  1. 在Global.asax.cs的Application_Start方法中,用反射替换自动生成的Resources类的静态resourceMan字段:
protected void Application_Start()
{
    // 从配置读取当前要切换的目标动物(可根据业务逻辑动态调整,比如从用户设置读取)
    var targetAnimal = ConfigurationManager.AppSettings["CurrentAnimal"] ?? "Dog";

    // 获取Resources类的私有静态resourceMan字段
    var resourceType = typeof(Resources);
    var resourceManField = resourceType.GetField("resourceMan", BindingFlags.Static | BindingFlags.NonPublic);
    if (resourceManField == null) return;

    // 实例化自定义ResourceManager并替换原有实例
    var patchedManager = new PatchedResourceManager(resourceType, targetAnimal);
    resourceManField.SetValue(null, patchedManager);
}

优点:完全不需要修改现有视图和业务代码,所有资源访问自动经过补丁处理;缺点:依赖反射,需要确保自动生成的Resources类结构不变(通常默认生成的结构稳定)。

方案2:HtmlHelper扩展方法(低侵入性,可控修改)

如果不想用反射,可以通过扩展HtmlHelper的方式,封装资源读取和补丁逻辑,然后批量替换视图中的资源调用。

实现步骤:

  1. 创建HtmlHelper扩展类:
public static class LocalizationExtensions
{
    public static MvcHtmlString Localized(this HtmlHelper helper, string resourceKey)
    {
        var culture = helper.ViewContext.HttpContext.Request.UserLanguages?.FirstOrDefault() 
                      ?? Thread.CurrentThread.CurrentUICulture.Name;
        var original = Resources.ResourceManager.GetString(resourceKey, new CultureInfo(culture));
        var patched = PatchString(original, culture);
        return MvcHtmlString.Create(patched);
    }

    private static string PatchString(string original, string cultureName)
    {
        var targetAnimal = ConfigurationManager.AppSettings["CurrentAnimal"] ?? "Dog";
        if (string.IsNullOrEmpty(original)) return original;

        return cultureName switch
        {
            "en-US" => original.Replace("dog", targetAnimal.ToLower())
                               .Replace("Dog", targetAnimal)
                               .Replace("dogs", $"{targetAnimal}s"),
            "zh-CN" => original.Replace("狗狗", targetAnimal switch 
                       { 
                           "Cat" => "猫咪", 
                           "Squirrel" => "松鼠", 
                           _ => "狗狗" 
                       }),
            _ => original
        };
    }
}
  1. 批量替换视图中的资源调用:
    在Visual Studio中使用查找替换(开启正则表达式),查找模式为@Resources\.(\w+),替换模式为@Html.Localized("$1"),一键完成所有视图的修改。

优点:实现简单,不依赖反射,逻辑清晰;缺点:需要修改所有视图中的资源调用代码(但可通过正则批量替换完成)。

方案3:自定义资源访问包装类(适用于业务代码和视图共用)

如果业务代码中也有大量直接访问Resources的场景,可以封装一个静态包装类,统一处理资源读取和补丁:

public static class LocalizationService
{
    public static string GetString(string resourceKey)
    {
        var culture = Thread.CurrentThread.CurrentUICulture;
        var original = Resources.ResourceManager.GetString(resourceKey, culture);
        return PatchString(original, culture);
    }

    private static string PatchString(string original, CultureInfo culture)
    {
        // 替换逻辑同方案1,省略重复代码
    }
}

然后业务代码中用LocalizationService.GetString("AllDogs")替代Resources.AllDogs,视图中用@LocalizationService.GetString("AllDogs"),同样可以用正则批量替换现有代码。


内容的提问来源于stack exchange,提问作者Sebi O.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 01:32:50