如何从 .NET 资源(RESX)文件中通过字符串值获取名称

21

以下是我的RESX文件的样子:

Name            Value        Comments
Rule_seconds    seconds      seconds
Rule_Sound      Sound        Sound

我想要的是:根据字符串值命名,类似下面这样:

public string GetResxNameByValue(string value)
{
// some code to get name value
}

然后像下面这样实现:

string str = GetResxNameByValue("seconds");

这样str将返回Rule_seconds

谢谢!


似乎只有在资源文件确保没有重复值的情况下才能实现这一点,否则可能会返回意外的资源键。例如,如果您有两个名称/键(Time_Second、Sequence_Second),它们都具有“second”的值。当您期望另一个时,您可能会得到“Time_second”的名称。 - cli
7个回答

29
这个可能行
private string GetResxNameByValue(string value)
{
    System.Resources.ResourceManager rm = new System.Resources.ResourceManager("YourNamespace.YourResxFileName", this.GetType().Assembly);
    var entry = rm.GetResourceSet(System.Threading.Thread.CurrentThread.CurrentCulture, true, true)
        .OfType<DictionaryEntry>()
        .FirstOrDefault(e => e.Value.ToString() ==value);

    var key = entry.Key.ToString();
    return key;
}

通过一些额外的错误检查..

谢谢,如果资源文件在程序集中而不是项目中的实际(RESX)文件,该怎么办? - Learner
您可以在ResourceManager构造函数中指定资源嵌入的程序集。但是,您仍然必须知道资源的基本名称。如果不知道,可以使用Assembly.GetMainfestResourceNames来查找嵌入到程序集中的资源。 - Jurica Smircic
@jure:是否有可能从资源中返回所有键值对? - Kuldeep Singh

5
您可以通过传递密钥直接访问:
    public  string gtresource(string rulename)
    {
        string value = null;
        System.Resources.ResourceManager RM = new System.Resources.ResourceManager("CodedUITestProject1.Resource1", this.GetType().Assembly);
        value = RM.GetString(rulename).ToString();

        if(value !=null && value !="")
        {
            return value;

        }
        else
        {
            return "";
        }

    }

3
在这7行代码中,我看到有几个问题需要解决:首先,RM.GetString(rulename)已经返回一个字符串,不需要调用ToString()。其次,如果资源未找到,RM.GetString(rulename)可能会返回null,从而引发NullReferenceException。第三,由于NullReferenceException的存在,if(value !=null && value !="")永远不会执行到null值。最后,你可以用return RM.GetString(rulename) ?? string.Empty;替换所有的if。 - PhilDulac
3
这并没有回答原来的问题,原问题与您发布的解决方案是相反的。需要检索一个特定值对应的键... - Youp Bernoulli

2

以防有所帮助。此ResourceHelper受到jureMohan Singh Saini的启发。

using System.Collections;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Threading;

public class ResourceHelper
{
    /// <summary>
    ///     ResourceHelper
    /// </summary>
    /// <param name="resourceName">i.e. "Namespace.ResourceFileName"</param>
    /// <param name="assembly">i.e. GetType().Assembly if working on the local assembly</param>
    public ResourceHelper(string resourceName, Assembly assembly)
    {
        ResourceManager = new ResourceManager(resourceName, assembly);
    }

    private ResourceManager ResourceManager { get; set; }

    public string GetResourceName(string value)
    {
        DictionaryEntry entry = ResourceManager.GetResourceSet(Thread.CurrentThread.CurrentCulture, true, true).OfType<DictionaryEntry>().FirstOrDefault(dictionaryEntry => dictionaryEntry.Value.ToString() == value);
        return entry.Key.ToString();
    }

    public string GetResourceValue(string name)
    {
        string value = ResourceManager.GetString(name);
        return !string.IsNullOrEmpty(value) ? value : null;
    }
}

有没有想法如何在引用的项目中引用字符串资源?每次尝试引用时都会出现异常。 - BrianS
我找到了。对于已加载的RESX文件,您可以引用内置的资源管理器。请参见https://dev59.com/HXI_5IYBdhLWcg3wJPhu#22494089。 - BrianS
@BrianS 谢谢您的补充 :) - oloopy

2
简单直接的方法是 -
var keyValue = Resources.ResourceManager.GetString("AboutTitle");

在上述内容中,“AboutTitle”是“KEY”的关键部分,因此如果在资源中有“AboutTitle= About”,则上述结果为keyValue = About
我已经在我的一个VS2019项目中使用了这个。

1
public static class ResourceManagerHelper
{
    public static string GetResourceName(this ResourceManager resourceManager, string value, CultureInfo cultureInfo, bool ignoreCase = false)
    {
        var comparisonType = ignoreCase ? System.StringComparison.OrdinalIgnoreCase : System.StringComparison.Ordinal;
        var entry = resourceManager.GetResourceSet(cultureInfo, true, true)
                                   .OfType<DictionaryEntry>()
                                   .FirstOrDefault(dictionaryEntry => dictionaryEntry.Value.ToString().Equals(value, comparisonType));

        if (entry.Key == null)
            throw new System.Exception("Key and value not found in the resource file");

        return entry.Key.ToString();
    }
}

调用这个扩展方法,
var key = Resources.ResourceManager.GetResourceName(value, CultureInfo.InvariantCulture, true);

在这种情况下,我们不希望传递资源程序集,相反,我们可以使用特定资源的资源管理器来调用。

1
ResourceManagerHelper是ResourceManager的常见扩展。每个资源文件都有一个资源管理器,例如:Rule.resx是一个资源文件。然后调用Rule.ResourceManager.GetResourceName(val, mycultureinfo) - Shyam Sundar

0

以下是一个简短的示例,它:

  • 使用子文件夹中的资源文件
  • 使用不同于默认文化的文化

.

public static string GetLocalizedNameReversed(string value)
{
    ResourceManager rm = new ResourceManager($"YourNamespace.YourFolder.YourResourceFileName", assembly);

    var entry = rm.GetResourceSet(new CultureInfo("nb-NO"), true, true)
            .OfType<DictionaryEntry>()
            .FirstOrDefault(e => e.Value.ToString().Equals(value, StringComparison.OrdinalIgnoreCase));

    return entry.Key.ToString();
}

0
你可以使用这个内联代码(c#,ASP.NET MVC)。
var _resource = new ResourceManager(typeof(/*your resource*/));
string res = _resource.GetString(/*resource key*/);

我认为这可能会对你有所帮助。


为什么这个答案解决了提问者的问题? - sjaustirni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接