【问题标题】:Loop through all the resources in a .resx file循环遍历 .resx 文件中的所有资源
【发布时间】:2010-01-11 09:53:56
【问题描述】:

有没有办法在 C# 中循环遍历 .resx 文件中的所有资源?

【问题讨论】:

  • 您能否详细说明 RESX 文件是否在您的项目内部,或者您是否想要(或需要)读取单独的 RESX 文件或从另一个程序集读取 RESX?

标签: c# .net embedded-resource


【解决方案1】:

您应该始终使用资源管理器而不是直接读取文件,以确保将全球化考虑在内。

using System.Collections;
using System.Globalization;
using System.Resources;

...

/* Reference to your resources class -- may be named differently in your case */
ResourceManager MyResourceClass =
    new ResourceManager(typeof(Resources));

ResourceSet resourceSet =
    MyResourceClass.ResourceManager.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
foreach (DictionaryEntry entry in resourceSet)
{
    string resourceKey = entry.Key.ToString();
    object resource = entry.Value;
}

【讨论】:

  • 我花了一点时间才发现您需要这一行来声明 MyResourceClass。 ResourceManager MyResourceClass = new ResourceManager("Resources.ResourceFileName", System.Reflection.Assembly.Load("App_GlobalResources"));
  • @JoeFletch:它不需要这条线。代码直接调用资源文件。示例:我有一个名为 PageList.resx 的文件,然后我会调用:ResourceSet resourceSet = PageList.ResourceManager.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
  • @Gabriel,感谢您的更新!我将不得不返回我的代码来检查这一点。
  • JoeFletch 的台词实际上帮助了我。我在另一个 C# 项目中有一个 resx,所以他的行允许我调用该 dll 程序集并以这种方式加载资源。此外,当我尝试在我的代码中包含 PageList 时,它为 PageList.ResourceManager 引发了一个错误。说“PageList 不包含 ResourceManager 的定义”。最后,string resourceKey = entry.Key 报错了,我改用“object resourceKey = entry.Key”
  • 根据您的资源中是否确实定义了文化,您必须切换到 CultureInfo.InvariantCulture。这里我使用的是库中的资源,而不是 WinForms 应用程序。
【解决方案2】:

关于它的博客on my blog :) 简短版本是,查找资源的全名(除非你已经知道它们):

var assembly = Assembly.GetExecutingAssembly();

foreach (var resourceName in assembly.GetManifestResourceNames())
    System.Console.WriteLine(resourceName);

将它们全部用于某事:

foreach (var resourceName in assembly.GetManifestResourceNames())
{
    using(var stream = assembly.GetManifestResourceStream(resourceName))
    {
        // Do something with stream
    }
}

要在执行程序集以外的其他程序集中使用资源,您只需使用Assembly 类的其他一些静态方法即可获得不同的程序集对象。希望对你有帮助:)

【讨论】:

  • 你能列举not位于名为“Resource”的文件夹中的资源吗?我想在一个名为“Images”的文件夹中枚举位于我的项目中的所有资源图像。
  • 很确定它不关心它的位置?测试一下?
  • 我在一个文件夹中有用于导入 sql 文件的文件,这非常有效。我添加了从流到字符串的转换,因此我可以读取文件并且没有问题。
【解决方案3】:

使用ResXResourceReader Class

ResXResourceReader rsxr = new ResXResourceReader("your resource file path");

// Iterate through the resources and display the contents to the console.
foreach (DictionaryEntry d in rsxr)
{
    Console.WriteLine(d.Key.ToString() + ":\t" + d.Value.ToString());
}

【讨论】:

    【解决方案4】:

    在您将资源 .RESX 文件添加到项目的那一刻,Visual Studio 将创建一个同名的 Designer.cs,为您创建一个将资源的所有项作为静态属性的类。输入资源文件名后,在编辑器中输入圆点即可看到资源的所有名称。

    或者,您可以使用反射来遍历这些名称。

    Type resourceType = Type.GetType("AssemblyName.Resource1");
    PropertyInfo[] resourceProps = resourceType.GetProperties(
        BindingFlags.NonPublic | 
        BindingFlags.Static | 
        BindingFlags.GetProperty);
    
    foreach (PropertyInfo info in resourceProps)
    {
        string name = info.Name;
        object value = info.GetValue(null, null);  // object can be an image, a string whatever
        // do something with name and value
    }
    

    这种方法显然只在RESX文件在当前程序集或项目范围内时可用。否则,使用“脉冲”提供的方法。

    此方法的优点是您可以调用为您提供的实际属性,如果您愿意,可以考虑任何本地化。但是,它相当多余,因为通常您应该使用类型安全的直接方法来调用资源的属性。

    【讨论】:

    • 当有 ResourceSet 可用时为什么要使用反射?
    • 这也是我想知道的(见最后一段)。只是想展示一种替代方法,但更重要的是,想展示该类是完全可访问的,并且您不需要手动做任何魔术(第一段)。
    【解决方案5】:
      // Create a ResXResourceReader for the file items.resx.
      ResXResourceReader rsxr = new ResXResourceReader("items.resx");
    
      // Create an IDictionaryEnumerator to iterate through the resources.
      IDictionaryEnumerator id = rsxr.GetEnumerator();       
    
      // Iterate through the resources and display the contents to the console.
      foreach (DictionaryEntry d in rsxr) 
      {
    Console.WriteLine(d.Key.ToString() + ":\t" + d.Value.ToString());
      }
    
     //Close the reader.
     rsxr.Close();
    

    查看链接:microsoft example

    【讨论】:

    • 请注意,此类在 System.Windows.Forms 程序集中,如果您使用的是 MVC 应用程序,则不会自动添加
    【解决方案6】:

    您可以使用ResourceManager.GetResourceSet

    【讨论】:

      【解决方案7】:

      如果您想使用 LINQ,请使用 resourceSet.OfType<DictionaryEntry>()。例如,使用 LINQ 可以让您根据索引 (int) 而不是键 (string) 来选择资源:

      ResourceSet resourceSet = Resources.ResourceManager.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
      foreach (var entry in resourceSet.OfType<DictionaryEntry>().Select((item, i) => new { Index = i, Key = item.Key, Value = item.Value }))
      {
          Console.WriteLine(@"[{0}] {1}", entry.Index, entry.Key);
      }
      

      【讨论】:

        【解决方案8】:

        对于 nuget 包 System.Resources.ResourceManager (v4.3.0),ResourceSetResourceManager.GetResourceSet 不可用。

        使用ResourceReader,正如这篇文章所建议的那样:“C# - Cannot getting a string from ResourceManager (from satellite assembly)

        仍然可以读取资源文件的键/值。

        System.Reflection.Assembly resourceAssembly = System.Reflection.Assembly.Load(new System.Reflection.AssemblyName("YourAssemblyName"));
        String[] manifests = resourceAssembly.GetManifestResourceNames(); 
        using (ResourceReader reader = new ResourceReader(resourceAssembly.GetManifestResourceStream(manifests[0])))
        {
           System.Collections.IDictionaryEnumerator dict = reader.GetEnumerator();
           while (dict.MoveNext())
           {
              String key = dict.Key as String;
              String value = dict.Value as String;
           }
        }
        

        【讨论】:

          【解决方案9】:

          简单的读取循环使用此代码

          var resx = ResourcesName.ResourceManager.GetResourceSet(CultureInfo.CurrentUICulture, false, false);
          
          foreach (DictionaryEntry dictionaryEntry in resx)
          {
              Console.WriteLine("Key: " + dictionaryEntry.Key);
              Console.WriteLine("Val: " + dictionaryEntry.Value);
          }
          

          【讨论】:

            【解决方案10】:

            使用LINQ to SQL:

            XDocument
                    .Load(resxFileName)
                    .Descendants()
                    .Where(_ => _.Name == "data")
                    .Select(_ => $"{ _.Attributes().First(a => a.Name == "name").Value} - {_.Value}");
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-10-17
              • 1970-01-01
              • 2014-04-24
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多