【问题标题】:How to know if a resource file is not found without catching MissingManifestResourceException如何在不捕获 MissingManifestResourceException 的情况下知道是否找不到资源文件
【发布时间】:2015-11-26 17:41:32
【问题描述】:

对于我的应用程序的每个客户端,我都有位于不同命名空间中的 .resx 文件。说Resources.FirstClient.Home.resxResources.SecondClient.Home.resx。大多数字符串对于每个客户端都是通用的,所以我想引入一个默认命名空间Resources.Default.Home.resx,如果没有为客户端找到字符串,我可以使用它。

我的问题是我不知道如何确定是否找不到资源文件。 (例如 Resources.ThirdClient.Home.resx 不存在,所以我想改用 "Resources.Default.Home.resx

现在,我发现处理它的唯一方法是捕获 MissingManifestResourceException 抛出的:

var resourceManager = new ResourceManager("Resources.ThirdClient.Home", typeof(ResourceFactory).Assembly);

string str;
try
{
    str = resourceManager.GetString("myString");
}
catch(MissingManifestResourceException e)
{
    resourceManager = new ResourceManager("Resources.DefaultClient.Home", typeof(ResourceFactory).Assembly);
    str = resourceManager.GetString("myString");
}

有没有更好的方法知道资源文件是否丢失?

【问题讨论】:

  • 您可以尝试使用反射来检查该命名空间和模块是否存在,但是这种尝试捕获方法比花费精力锻炼反射方法要好得多。

标签: c# .net resources resourcemanager


【解决方案1】:

我们最终在应用程序启动时加载了ResourceManager 的实例并将它们保存在一个单例实例中,然后在尝试获取字符串时使用这些实例。

首先,我们将资源管理器加载到字典字典中,第一个键是客户端名称,第二个键是资源文件的名称(例如:resourceManagers["ThirdClient"]["Home"])。我们在 _tenants 列表中也有一个默认值:

var resourceManagers = new Dictionary<string, IDictionary<string, IResourceManagerAdapter>>();

foreach (var tenant in _tenants)
{
    var resourceDictionnary = typeof(ResourceFactory)
        .Assembly
        .GetTypes()
        .Where(t => t.IsClass && t.Namespace == "Resources." + tenant)
        .ToDictionary<Type, string, ResourceManager>
             (resourceFile => resourceFile.Name,
              resourceFile => new ResourceManager("Resources." + tenant + "." + resourceFile.Name, typeof(ResourceFactory).Assembly));

    resourceManagers.Add(tenant, resourceDictionnary);
}

我们将生成的 resourceManagers 字典保存在使用 DI 容器注入到我们的服务中的单例实例中。

然后我们使用注入的字典来获取字符串,如果没有找到则使用默认值:

public string GetString(string classKey, string resourceKey)
{
    if (!resourceManagers.ContainsKey(client) || !resourceManagers[client].ContainsKey(classKey))
        return resourceManagers[default][classKey].GetString(resourceKey);

    return resourceManagers[client][classKey].GetString(resourceKey, _cultureService.GetCurrentCulture())
        ?? resourceManagers[default][classKey].GetString(resourceKey);
}

根据我们所做的测试,这种方法比在每个GetString 上使用新的ResourceManagertry catch 快大约1000 倍。

【讨论】:

    猜你喜欢
    • 2011-03-24
    • 1970-01-01
    • 1970-01-01
    • 2019-05-30
    • 2021-09-06
    • 2022-11-11
    • 1970-01-01
    • 2018-09-22
    • 1970-01-01
    相关资源
    最近更新 更多