Thursday, February 1, 2007

A to Z of embedding resources

extarct resources from a dll

a question comes to mind how to view the embedded resources of a dll.

one way is to type WebResource.axd source location on the browser address bar and then either u'll get a download dialog or the file content in the browser.

another option (which might interesting for dev's) is to extract the resources from the dll itself.the below code only extracts the embedded resources.

void ExtractAssemblyResource()

{

// EmbeddedResources should be a class in the dll from which you want to extract the resources//

Assembly executingAssembly = Assembly.GetAssembly(typeof(EmbeddedResources));

//get the fully qualified resource names//


foreach (string resourceName in executingAssembly.GetManifestResourceNames())

{

//extract the file name from the '.' separated resource name

string[] resourcePart = resourceName.Split('.');

int startIndex = 0;

int indexCal = resourcePart.Length - 2;

foreach (string part in resourcePart)

{


if (indexCal-- > 0)

{

startIndex += part.Length + 1;

}

else

{

break;

}

}

string resource = resourceName.Substring(startIndex);

Console.WriteLine(resource);

//create stream from the resource and write a byte stream to a locale file//


Stream resourceStream = executingAssembly.GetManifestResourceStream(resourceName);

FileInfo aResource = new FileInfo(resource);

FileStream fAResource = aResource.OpenWrite();

byte[] content = new byte[resourceStream.Length];

resourceStream.Read(content, 0, content.Length);

fAResource.Write(content, 0, content.Length);

resourceStream.Close();

fAResource.Close();


}

}


common class for web resource
//provides functions to retrieve WebResourceUrl for the EmbeddedResources

public class Resources

{

private Page caller = null;

public Resources(Page page)

{

caller = page;

}

public void GetResourceUrl(string sourcePath)

{

if(caller != null)

GetResourceUrl(caller, sourcePath);

}

public static string GetResourceUrl(Page caller, string sourcePath)

{

return caller.ClientScript.GetWebResourceUrl(typeof(Resources), sourcePath);

}

}



//define constants for all the EmbeddedResources, specifying their location

public class ResourceConstants

{

public const string ARROW = "WebResources.arrow.jpg";

public const string BOXINGDAYGIFTICON = "WebResources.BoxingDayGiftIcon.gif";

}



ps: dont forget to change the build action property for the images, from content to EmbeddedResource



public partial class _Default : System.Web.UI.Page

{

protected void Page_Load(object sender, EventArgs e)

{

img1.Src = Resources.GetResourceUrl(Page, ResourceConstants.BOXINGDAYGIFTICON);

}

}






What is it?
Web Resource is a way to embedded all your less frequently changed items like images, css, js etc into a common dll and use it accross projects, intead of adding them individually to each project.

via web resource, you can embedded almost any type of resource like xhtml etc. but the ways to access them may vary.

the project i was doing, has absolute image path(~/images/icon_edit.gif) all over the place i.e. ASPX, CSS, JavaScript. the best and most reliable way to embbed resource is to prepare a separate dll only for the resource and use it whenever required.

enough of talking........lets start of with some solid work........

Create a Web Application Project (in case of console app, you have to force a dll out)
Clean up the project (just so that there is no junk i.e cs file)

Add a *.cs file to the project (EmbeddedResource.cs)

Add a folder (images) which contains a hierarchical arranged images. Select images and change there Property- 'Build Action' to 'Embedded Resource'.

Now comes the cumbersome part of making entries in the Assembly.info and creating a class to refer constant paths. best way out is to create a small program which can scan through a specific directory and all the sub-directory and generate a string for each file found (easier said then done)

entry for a single resource in

Assembly.info
------- [assembly: WebResource("XYZ.Resources.images.holidays.BoxingDayGiftIcon.gif", "image/gif")]

WebResource is under System.Web.UI.WebResourceAttribute

ResourceName i.e XYZ.Resources.images.holidays.BoxingDayGiftIcon.gif, defines the location of the resource in the assembly(dll). the string path is a collection of 3 parts i.e. Assembly Name + Folder name + Resource Name.
Here
'XYZ.Resources' is the assembly name
images - holidays are the folder separated by a '.'
boxingdaygifticon.gif is the resource name

ContentType i.e the type of the resource, in this case it is image/gif. we also used 'image/ico' , 'image/jpg'

ps : to check weather the resource has been added, use .net reflector to locate the above entry in the dll. if the entry is there, then the resource has been added.

EmbeddedResource.cs
------

public class EmbeddedResource
{
public static class Images
{
public static class Holidays
{
public const string BOXINGDAYGIFTICON = "XYZ.Resources.images.holidays.BoxingDayGiftIcon.gif";
}
}
}

now you are read with the dll. just include it in the project where required and assign the resource path by using the System.Web.UI.ClientScriptManager to GetResourceUrl (which provides a WebResource Url and various other things like registering client script, registering startup client script etc) to the appropriate control properties.


the toughest part of making all your existing absolute path to point to WebResource would be the entries in CSS.


*the next would be to extract the WebResource from the dll.