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

Blazor Server项目发布后如何编辑.resx资源文件?

在Blazor Server项目中实现发布后编辑.resx资源文件的功能

要实现发布后编辑.resx文件的需求,核心是避免资源文件被嵌入程序集,同时修改资源读取逻辑为直接读取物理文件,以下是具体步骤:

1. 修改项目配置,确保.resx文件被复制到发布目录

默认情况下,.resx文件会被嵌入程序集,无法在发布后直接编辑。需要修改项目文件(.csproj),将目标.resx文件设置为Content类型并指定发布时复制:

<ItemGroup>
  <!-- 配置需要编辑的.resx文件,发布时复制到输出目录 -->
  <Content Include="Resources\*.resx">
    <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
  </Content>
  <!-- 移除默认的嵌入资源配置,避免资源被打包进程序集 -->
  <EmbeddedResource Remove="Resources\*.resx" />
</ItemGroup>

注意:将Resources\*.resx替换为你实际的资源文件路径和匹配规则。

2. 实现自定义资源读取服务

创建一个服务类,负责从发布目录的物理文件中读取.resx内容,替代默认的嵌入资源读取逻辑:

using System.Resources;
using Microsoft.AspNetCore.Hosting;

public class PhysicalResourceReader
{
    private readonly string _resourceDirPath;

    public PhysicalResourceReader(IWebHostEnvironment env)
    {
        // 指向发布目录下的Resources文件夹,可根据实际结构调整
        _resourceDirPath = Path.Combine(env.ContentRootPath, "Resources");
    }

    public string GetResourceString(string resourceFileName, string key)
    {
        var fullFilePath = Path.Combine(_resourceDirPath, $"{resourceFileName}.resx");
        
        // 文件不存在时返回key本身作为 fallback
        if (!File.Exists(fullFilePath))
            return key;

        using var reader = new ResXResourceReader(fullFilePath);
        var resourceDict = reader.Cast<DictionaryEntry>()
                                 .ToDictionary(entry => entry.Key.ToString(), 
                                               entry => entry.Value.ToString());

        return resourceDict.TryGetValue(key, out var value) ? value : key;
    }
}

在Program.cs中注册这个服务:

builder.Services.AddScoped<PhysicalResourceReader>();

3. 在Blazor组件中使用自定义资源读取服务

在需要显示资源字符串的Razor组件中,注入服务并调用方法获取内容:

@inject PhysicalResourceReader ResourceReader

<div>
    <h3>@ResourceReader.GetResourceString("AppResources", "WelcomeTitle")</h3>
    <p>@ResourceReader.GetResourceString("AppResources", "WelcomeContent")</p>
</div>

4. 发布后编辑.resx的注意事项

  • 发布完成后,publish目录下会生成Resources文件夹(对应你配置的路径),直接用文本编辑器或专门的.resx编辑器修改文件即可。
  • 上述读取逻辑每次都会读取物理文件,修改后无需重启应用即可生效。如果需要优化性能,可以添加内存缓存(如下方示例),但需配套缓存刷新机制。
  • 确保应用进程对publish/Resources目录有读写权限(比如IIS应用池身份需具备该目录的权限)。

可选:添加缓存优化(避免重复读取文件)

如果资源文件不会频繁修改,可添加内存缓存减少IO操作,同时提供手动刷新缓存的方法:

using System.Resources;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Caching.Memory;

public class CachedPhysicalResourceReader
{
    private readonly string _resourceDirPath;
    private readonly IMemoryCache _cache;
    private readonly MemoryCacheEntryOptions _cacheOptions = new()
        .SetSlidingExpiration(TimeSpan.FromMinutes(15));

    public CachedPhysicalResourceReader(IWebHostEnvironment env, IMemoryCache cache)
    {
        _resourceDirPath = Path.Combine(env.ContentRootPath, "Resources");
        _cache = cache;
    }

    public string GetResourceString(string resourceFileName, string key)
    {
        var cacheKey = $"Res_{resourceFileName}_{key}";
        
        // 优先从缓存读取
        if (_cache.TryGetValue(cacheKey, out string value))
            return value;

        var fullFilePath = Path.Combine(_resourceDirPath, $"{resourceFileName}.resx");
        if (!File.Exists(fullFilePath))
            return key;

        using var reader = new ResXResourceReader(fullFilePath);
        var resourceDict = reader.Cast<DictionaryEntry>()
                                 .ToDictionary(entry => entry.Key.ToString(), 
                                               entry => entry.Value.ToString());

        value = resourceDict.TryGetValue(key, out var val) ? val : key;
        _cache.Set(cacheKey, value, _cacheOptions);
        
        return value;
    }

    // 手动刷新指定资源文件的缓存(可在管理页面调用)
    public void RefreshResourceCache(string resourceFileName)
    {
        var cacheKeys = _cache.GetKeys().Where(k => k.ToString().StartsWith($"Res_{resourceFileName}_"));
        foreach (var key in cacheKeys)
        {
            _cache.Remove(key);
        }
    }
}

注册缓存版服务:

builder.Services.AddScoped<CachedPhysicalResourceReader>();
builder.Services.AddMemoryCache();

内容的提问来源于stack exchange,提问作者Shyam Sunder Agrahari

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 02:30:43