I have a program that contains a number of icons in an "Icons" folder (which are included in the project with Build Act开发者_如何转开发ion=Resource).
In XAML I can access these icons with code such as <Image Source="../Icons/name.png"/>
(".." because the XAML is in a different subfolder); however I want to use the same image in some WinForms code in the same project. Unfortunately,
GetType().Assembly.GetManifestResourceStream("Icons/name.png");
returns null
and
GetType().Assembly.GetManifestResourceNames()
only lists a bunch of *.resources files (one for each .resx and one called *.g.resources). So how am I supposed to get the image stream?
I assumed that since I included the images directly in my project that I could directly read them. But thanks to Jack's answer I was able to figure out that they are hidden inside a "resource file" named "ProgramName.g.resources" inside the assembly. To read the image it is necessary to load the resource file first, then search for the image file within the resource file.
ResourceSet.GetObject
is case-sensitive, but the image path and filename were converted to lowercase for some reason, so I call ToLowerInvariant
on the path name. Here's my solution:
private Stream GetGlobalResourceByPath(Assembly assembly, string path)
{
string name = assembly.GetManifestResourceNames().Where(n => n.EndsWith(".g.resources")).First();
Stream outerStream = assembly.GetManifestResourceStream(name);
ResourceSet resources = new ResourceSet(outerStream);
return resources.GetObject(path.ToLowerInvariant()) as UnmanagedMemoryStream;
}
I'm not sure how expensive it is to construct a ResourceSet
. If it's expensive, and you want to retrieve multiple resources, then you should cache and re-use the ResourceSet
object.
Please leave a message if you know why the images end up inside the *.g.resources file. Did Visual Studio choose this name? Is it theoretically possible to put images directly in an assembly, or can assemblies only contain "ResourceSets"?
you can find some help from:
http://blog.devarchive.net/2007/12/net-assembly-resource-browser-test.html
http://msdn.microsoft.com/en-us/library/system.io.unmanagedmemorystream.aspx
In the first link, you can find a way to get the resource that is type of UnmanagedMemoryStream, then you should find a way to convert the stream to the type you want.
Hope it helps you!
foreach (var resourceName in ThemeList.Current.GetType().Assembly.GetManifestResourceNames())
{
var resourceStream = GetType().Assembly.GetManifestResourceStream(resourceName);
ResourceSet resources = new ResourceSet(resourceStream);
IDictionaryEnumerator enu = resources.GetEnumerator();
while (enu.MoveNext())
{
Console.WriteLine(enu.Key); // Key is the resource name and Value is UnmanagedMemoryStream
}
}
精彩评论