【问题标题】:Loading resources from external dll, and determining the resource type从外部dll加载资源,并确定资源类型
【发布时间】:2016-09-19 22:13:53
【问题描述】:

我有一个 C# 应用程序,将我们所有的资源都放在一个库中。这基本上是几个文件夹,每个文件夹中都有一个或多个 .resx 文件。

在大多数情况下,.resx 文件都有字符串资源。少数有文件资源。

我的任务是浏览这些字符串资源并用它们做一些事情。只是字符串,而不是文件。

目前,我可以从单独的 dll 加载资源:

var asm = System.Reflection.Assembly.LoadFrom("External.Resources.dll");

string[] strings = asm.GetManifestResourceNames();

foreach (var s in strings)
{
    var rm = new ResourceManager(s, asm);

    var rs = rm.GetResourceSet(CultureInfo.CurrentCulture, true, true);

    foreach (DictionaryEntry de in rs)
    {
        var val = de.Value.ToString();
        var key = de.Key.ToString();
    }
}

不幸的是,我无法判断资源是什么。如果是文件,则 Value 将只包含该文件的文本。

如何检查该值是来自资源文件的字符串还是文件(文本)?

【问题讨论】:

    标签: c# embedded-resource


    【解决方案1】:

    如果您想获取原始资源类型,则必须访问原始资源对象。它将具有特定类型的静态属性;例如文件将是字节[],字符串为字符串等。

    var asm = System.Reflection.Assembly.LoadFrom("External.Resources.dll");
    string[] strings = asm.GetManifestResourceNames();
    
    foreach (var s in strings)
    {
        var rm = new ResourceManager(s, asm);
    
        // Get the fully qualified resource type name
        // Resources are suffixed with .resource
        var rst = s.Substring(0, s.IndexOf(".resource"));
        var type = asm.GetType(rst, false);
    
        // if type is null then its not .resx resource
        if (null != type)
        {
            var resources = type.GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
            foreach (var res in resources)
            {
                // collect string type resources
                if (res.PropertyType == typeof(string))
                {
                    // get value from static property
                    string myResourceString = res.GetValue(null, null) as string;
                }
            }
        }
    
    }  
    

    【讨论】:

    • 文件应该总是字节[]?我使用您的代码并针对我的资源库运行它,它仍在提取文本文件的内容,因此 res PropertyType 仍然是 String,GetValue 返回一个字符串(文件的内容)。您可以通过创建另一个dll项目,添加资源文件,添加文本文件并将其作为文件资源添加到resx文件来进行模拟。
    • 文本文件自动转换为字符串。这是默认行为,因为基于文化的输出/转换可能需要它们。唯一可以区分它是否真的是文件的方法是读取原始的 .resx xml 文件(该文件在程序集中不直接可用)。否则,假设字符串是来自文件还是来自资源文本将是有问题的。
    【解决方案2】:

    “循环代码”代码的 LINQ 版本应如下所示:

     var asm = System.Reflection.Assembly.LoadFrom("External.Resources.dll");
     string[] strings = asm.GetManifestResourceNames();
     string myResourceString=null;
      foreach (var res in from s in strings
                                    select s.Substring(0, s.IndexOf(".resource"))
                                    into rst
                                    select asm.GetType(rst, false)
                                    into type
                                    where null != type
                                    select type.GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
                                    into resources
                                    from res in resources
                                    where res.PropertyType == typeof(string)
                                    select res)
            {
                myResourceString = res.GetValue(null, null) as string;
            }
    

    投票给“loopedcode”答案不是我的。我的代码是使用 Resharper 从他的原始代码开始创建的,我只是做了一些更改并删除了一个无用的指令:

    var rm = new ResourceManager(s, asm);
    

    【讨论】:

      【解决方案3】:

      根据您的代码,最直接的方法是调用 ResourceSet.GetString(de.Key) 并为非字符串资源捕获 InvalidOperationException。效率不是很高,但我假设你在这里建立一个缓存,所以这是一次性成本。

      【讨论】:

      • 我有几种不同的访问方式,但问题的核心是您解决的问题。如果(例如)我的资源文件中有一个链接到的 .sql 文件,那么当我调用值时,它是一个字符串。所以在这种情况下,ResourceSet.GetString(de.Value) 将返回 SQL 文件的内容。
      • 其实应该是de.Key
      • 我知道。我要说的是结果将是一个字符串,无论它是字符串资源还是包含文本的文件。它不会抛出任何异常,只是返回文件的内容。
      • 我没有意识到你的意思是文本文件(相对于其他非 ascii 文件的图像)。
      • 不用担心,感谢您抽出宝贵时间帮助我。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-13
      • 1970-01-01
      • 1970-01-01
      • 2017-08-06
      • 2014-02-13
      相关资源
      最近更新 更多