In Visual Studio I have several ways to include resources into my project:
- Solution Explorer → My Project → Right Click → Properties → Resources → Add Resource
- Copy file to solution directory → Solution Explorer → Show all Files → Right Click → Include in Project → Right Click → Properties → Build Action → Resource
- Copy file to solution directory → Solution Explorer → Show all Files → Right Click → Include in Project → Right Click → Properties → Build Action → Embedded Resource
- Some more?
My questions are:
- What are the differences of these resources?
- How can I access them by code (C#)?
- Is it possible to add new resources by code?
Best Answer
Storage
For #1, the resource that you add is stored in XML format in a file named
Resources.resx
, typically located in theProperties
subfolder of a WinForms or WPF application that is created using the default Visual Studio templates.For #2 and #3, the resource (file) is included in the project (ie. the Visual Studio project knows about the file, it will be added to source control if that is applicable for the project, etc), the difference is in how the compiler includes the contents of the file as part of the resulting assembly. #2 is typically used for WPF applications; #3 for WinForms applications.
Access
#1 (Resources.resx)
The resources are accessed via an auto-generated class called
Resources
. For example, if you add a bitmap resource namedMyBitmap
you can access that as follows:#2 (Build Action = Resource)
The resources can be referenced from XAML (markup) or code. For XAML, several of the standard controls support resource references. For example, the
Image
control has aSource
property that by default references an embedded resource. To reference a resource file named "wpf.jpg" contained in the root of your WPF project:If the file was in a subfolder named "images":
To access these resources from code, you use the
GetResourceStream
method of theApplication
class, passing a reference to the desired resource in the form of a pack URI. Using the file in the above example:Once you have the stream you can do what you want with it.
#3 (Build Action = Embedded Resource)
You need to get a reference to the assembly containing the resource, then call the
GetManifestResourceStream
method to obtain a stream for it. What you do with the stream depends on the type of resource you're dealing with. For example, this will create a bitmap from a named resource:Getting the right resource name can be tricky. It is generally a concatenation of the assembly name, and the folder and file name of the resource. For example, a file named "MyBitmap.bmp" in a folder named "Resources" in a project named "WindowsFormsApplication1" would be compiled to a resource named
WindowsFormsApplication1.Resources.MyBitmap.bmp
. That's the string you would pass to theGetManifestResourceStream
method.Adding new resources
As the resources are compiled into the assembly (EXE or DLL), adding new resources cannot be done without recompiling the assembly. The only programmatical way of doing this that I know of is to use a NuGet package called Mono.Cecil.