Tip: Accessing Binary Resources in Portable Class Library

August 10, 2014

no comments

Portable Class Libraries (PCLs) provide a nice way to share code by allowing the library to be referenced from a number of different types of projects. As I’ve blogged before, when targeting Windows Phone 8.1 and Windows 8.1 the common surface for the PCL grows significantly and even allows sharing of XAML and other UI-related types. However, when targeting more frameworks such as the desktop .NET, the common surface drops significantly. One of the things we may want to do is to add some binary resource (image, XML file, etc.) and process it as part of the PCL. This is not as easy as it appears in first glance.

Considering classes such as FileStream is not an option. This (and related classes) is not part of a PCL (Windows Store doesn’t support it, nor does Windows Phone). The other intuition that may come up is using the classic .NET ResourceManager class (with a RESX file) and pulling such resources from there. This fails as well, however. PCLs do provide some support for ResourceManager, but it only support strings as resources – not arbitrary binary resources.

Let’s create a simple example. I’ve created a PCL that targets Windows 8, Windows Phone 8 and .NET 4.5 named DemoLibrary:

image

Now let’s add some binary file to the project, such as some XML file named Demo.xml:

image

What I want to do is to be able to load that XML at runtime and do something with it.

One possible solution is to use a CodePlex library called PCLStorage that provides an abstraction layer over file system operations. However, this still requires the actual non-PCL project (that uses the PCL) to add its own reference to PCL Storage for the actual implementation. This solution is viable, but it still makes the PCL dependent on something; I’d rather have the PCL totally independent.

It turns out there is a way to access that resource in a PCL-friendly way. The secret is the Assembly.GetManifestResourceStream method. It accepts a string that is the name of the resource, composed of the assembly name and the file name. Make sure the build action on the resource is set to Embedded Resource:

image

Now we can access the resource. Before we can call GetManifestResourceStream we need a reference to the assembly which turns out to be somewhat of a challenge. Assembly.GetExecutingAssembly does not exist in a PCL, and not even the Type.Assembly property. Fortunately, there is a way: using the GetTypeInfo extension method on Type (from System.Reflection). The end result is something like this:

public int DoWork() {
     var stm = GetType().GetTypeInfo().Assembly.GetManifestResourceStream("DemoLibrary.Demo.xml");
     var xml = XElement.Load(stm);
     return xml.DescendantNodes().Count();
}
 

If you get a null stream, check the Build Action. If it looks ok, there’s probably something wrong with the resource name. An easy way to fix this is to call Assembly.GetManifestResourceNames to get an array of all embedded resources in the assembly; the proper name will show up.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*