从程序集中作为流获取资源

32
我在 C# WPF 应用中有一个图像,其“生成操作”设置为“资源”。它只是源目录中的一个文件,尚未通过拖放属性对话框将其添加到应用程序的资源集合中。我正在尝试将其作为流写入,但尽管尝试了很多不同的点、斜杠、命名空间和其他看似一切可行的方式,但无法打开它。
我可以在 XAML 中使用“pack://application:,,,/Resources/images/flags/tr.png”访问它以在其他地方使用,但我无法获取包含它的流。
大多数地方都建议使用:
using(BinaryReader reader = new BinaryReader(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("ResourceBlenderExpress.Resources.images.flags.tr.png"))) {
    using(BinaryWriter writer = new BinaryWriter(File.OpenWrite(imageFile))) {
        while((read = reader.Read(buffer, 0, buffer.Length)) > 0) {
            writer.Write(buffer, 0, read);
        }
        writer.Close();
    }
    reader.Close();
}

我一直没有成功过。

4个回答

37

你可能正在寻找Application.GetResourceStream

StreamResourceInfo sri = Application.GetResourceStream(new Uri("Images/foo.png"));
if (sri != null)
{
    using (Stream s = sri.Stream)
    {
        // Do something with the stream...
    }
}

7
需要补充的是,文件必须被构建为“资源”类型。https://dev59.com/wGs05IYBdhLWcg3wLe8j#7394894 - net_prog

29

GetManifestResourceStream 方法用于访问传统 .NET 资源,即在 RESX 文件中引用的资源。这些资源与 WPF 资源不同,即使用 Resource 的构建操作添加的资源。要访问这些资源,您应该使用 Application.GetResourceStream,并传递适当的 pack: URI。这将返回一个 StreamResourceInfo 对象,该对象具有一个 Stream 属性,可访问资源的数据。


8
如果我没理解错的话,您无法打开资源流,因为您不知道它的确切名称?如果是这样,您可以使用
System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames()

获取所有包含资源的名称列表。这样,您就可以找到分配给您的图像的资源名称。


1
为什么不使用GetExecutingAssembly而是使用GetCallingAssembly呢? - Odys
Application.ResourceAssembly可能是获取包含应用程序资源的程序集的首选方式。此外,本回答针对resx文件,而不是WPF资源文件,这也是本问题所涉及的。 - Kelly Elton

-2

不需要调用Close()方法,它会在using语句结束时由Dispose()自动调用。因此,您的代码可能如下所示:

using(BinaryReader reader = new BinaryReader(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("ResourceBlenderExpress.Resources.images.flags.tr.png")))
using(BinaryWriter writer = new BinaryWriter(File.OpenWrite(imageFile))) 
{
    while((read = reader.Read(buffer, 0, buffer.Length)) > 0) 
    {
        writer.Write(buffer, 0, read);
    }
}

1
这个回答如何回答问题? - Frank Bollack
真的吗?如果是真的,那就是非常有见地的。我一直以为对于流/文件来说,明确调用Close方法更好。 - Echilon
Using语句的使用显式地调用了Stream的dispose方法,该方法隐式地调用了它的Close方法。此外,using语句始终会处理“已使用”的对象,即使出现异常,因此using是一个全包容、几乎无故障的语句。 - BeardinaSuit

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