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

ASP.NET Core项目:不修改视图访问模式实现域特定资源的最简方案

不修改视图静态访问模式的域特定资源切换最简方案

核心思路

保留视图中@Resource.XXX的静态调用方式,通过自定义一个和原自动生成类同名同命名空间的静态类,内部动态根据当前域切换对应的资源集,完全兼容现有代码。

具体实现步骤

1. 保留域独立的资源文件结构

保持资源文件按域分目录存放,每个域下的.resx文件会自动生成对应命名空间的强类型Designer类:

project/Resources/Domain1/
- resource.resx → 生成类:project.Resources.Domain1.Resource
- resource.en.resx
- resource.en-GB.resx
- resource.en-US.resx

project/Resources/Domain2/
- resource.resx → 生成类:project.Resources.Domain2.Resource
- resource.en.resx
- resource.en-GB.resx
- resource.en-US.resx

注意:确保每个域下的.resx文件的「自定义工具」设置为ResXFileCodeGenerator,自动生成强类型属性。

2. 替换原全局Resource类

删除或禁用原project/Resources/resource.resx的自动生成(将其「自定义工具」清空),手动创建project/Resources/Resource.cs静态类,命名空间和类名与原自动生成类完全一致:

using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Reflection;

namespace project.Resources
{
    public static class Resource
    {
        private static IHttpContextAccessor _httpContextAccessor;
        private static readonly Dictionary<string, Type> _domainResourceTypes = new Dictionary<string, Type>();

        // 初始化方法,在Program.cs中注册
        public static void Initialize(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        // 根据当前域获取对应的资源类类型
        private static Type GetCurrentDomainResourceType()
        {
            string currentDomain = GetCurrentDomainIdentifier();
            
            if (_domainResourceTypes.TryGetValue(currentDomain, out var type))
                return type;

            // 反射加载对应域的Resource类
            Type resourceType = Assembly.GetExecutingAssembly().GetType($"project.Resources.{currentDomain}.Resource");
            if (resourceType == null)
                //  fallback到默认资源类
                resourceType = Assembly.GetExecutingAssembly().GetType("project.Resources.Default.Resource");

            _domainResourceTypes[currentDomain] = resourceType;
            return resourceType;
        }

        // 实现和原自动生成类一致的强类型属性,动态调用对应域的资源属性
        public static string WelcomeMessage
        {
            get
            {
                var resourceType = GetCurrentDomainResourceType();
                return (string)resourceType.GetProperty(nameof(WelcomeMessage)).GetValue(null);
            }
        }

        // 复制原自动生成类的所有资源属性,替换get逻辑即可
        public static string LoginButtonText
        {
            get
            {
                var resourceType = GetCurrentDomainResourceType();
                return (string)resourceType.GetProperty(nameof(LoginButtonText)).GetValue(null);
            }
        }

        // 自定义逻辑:根据请求获取当前域标识
        private static string GetCurrentDomainIdentifier()
        {
            var context = _httpContextAccessor.HttpContext;
            if (context == null)
                return "Default";

            // 示例:从请求域名判断域标识
            return context.Request.Host.Host switch
            {
                "domain1.com" => "Domain1",
                "domain2.com" => "Domain2",
                _ => "Default"
            };
        }
    }
}

3. 注册依赖并初始化

在Program.cs中注册IHttpContextAccessor并初始化自定义Resource类:

var builder = WebApplication.CreateBuilder(args);

// 注册HttpContextAccessor用于获取请求上下文
builder.Services.AddHttpContextAccessor();

var app = builder.Build();

// 初始化全局Resource类
project.Resources.Resource.Initialize(app.Services.GetRequiredService<IHttpContextAccessor>());

// ...其他中间件配置

4. 视图无需任何修改

原有视图代码完全保留,不需要做任何改动:

@using Resource = project.Resources.Resource;

<span>@Resource.WelcomeMessage</span>

方案优势

  • 100%兼容现有视图代码,无需修改任何@Resource.XXX调用
  • 支持域目录式资源结构,资源分类管理清晰
  • 复用自动生成的强类型Designer类,避免手动维护资源键名
  • 缓存已加载的资源类类型,反射性能影响极小

备选简化方案(资源属性较少时)

如果项目中资源属性不多,可直接通过ResourceManager动态加载资源,无需依赖每个域的Designer类:

using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Resources;

namespace project.Resources
{
    public static class Resource
    {
        private static IHttpContextAccessor _httpContextAccessor;
        private static readonly Dictionary<string, ResourceManager> _resourceManagers = new Dictionary<string, ResourceManager>();

        public static void Initialize(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        private static ResourceManager GetCurrentResourceManager()
        {
            string currentDomain = GetCurrentDomainIdentifier();
            if (_resourceManagers.TryGetValue(currentDomain, out var rm))
                return rm;

            var rm = new ResourceManager($"project.Resources.{currentDomain}.resource", typeof(Resource).Assembly);
            _resourceManagers[currentDomain] = rm;
            return rm;
        }

        public static string WelcomeMessage => GetCurrentResourceManager().GetString(nameof(WelcomeMessage));
        public static string LoginButtonText => GetCurrentResourceManager().GetString(nameof(LoginButtonText));

        private static string GetCurrentDomainIdentifier()
        {
            var context = _httpContextAccessor.HttpContext;
            return context?.Request.Host.Host switch
            {
                "domain1.com" => "Domain1",
                "domain2.com" => "Domain2",
                _ => "Default"
            };
        }
    }
}

内容的提问来源于stack exchange,提问作者M. Ozn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 08:10:58