Wednesday, September 16, 2009

How I did resource files with WSP builder and SharePoint in a DataFormWebPart

Resource files can be either in a .resources format or a .resx format. Visual Studio works great with .resx files where you can call the resource directly via a static class.

Resx files can be put in 12/Resources like core.resx, but I couldn’t get this to work out of the box.  After some googling and trying out different things, this is my receipt  on how to develop a SharePoint webpart and use resources with XSLT.

Firstly create a folder called Resources in the root of your project, and then add your resx files there.

resx

Then I added a class to handle the lookup of resources

public class ResourceHandler
{
private static readonly ResourceManager _resourceManager;
public static readonly ResourceHandler Instance = new ResourceHandler();

static ResourceHandler()
{
if (_resourceManager == null)
{
Type type = typeof(FrontResources);
_resourceManager = new ResourceManager("webparts.front.Resources.FrontResources", type.Assembly);
}
}

public string GetLabel(string key)
{
return GetLabel(key, HttpContext.Current);
}

public string GetLabel(string key, HttpContext context)
{
if(!HasKey(key, context)) return key;
return _resourceManager.GetString(key, GetCulture(context));
}

public bool HasKey(string key, HttpContext context)
{
ResourceSet rs = _resourceManager.GetResourceSet(GetCulture(context), true, true);
IDictionaryEnumerator ide = rs.GetEnumerator();
while (ide.MoveNext())
{
if (ide.Key.Equals(key)) return true;
}
return false;
}

private CultureInfo GetCulture(HttpContext context)
{
if (context.Request.UserLanguages.Length > 0)
{
try
{
return new CultureInfo(context.Request.UserLanguages[0]);
}
catch (ArgumentException)
{
return CultureInfo.CurrentUICulture;
}
}
return CultureInfo.CurrentUICulture;
}
}

The HasKey function was added due to the XSLT failing if accessing a key which wasn’t present, even if I try/catch around _resourceManager.GetString.

Inside the DataFormWebPart I override ModifyXsltArgumentList in order to add a namespace for the ResourceHandler in the xslt.
protected override void ModifyXsltArgumentList(ArgumentClassWrapper argList)
{
argList.AddExtensionObject("http://schemas.company.no/SharePoint/Label", ResourceHandler.Instance);
base.ModifyXsltArgumentList(argList);
}

And in the xslt you access a resource in the following way:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:front="http://schemas.company.no/SharePoint/Label">
<xsl:output method="xml" indent="yes"/>

<xsl:template match="/">
<xsl:value-of select="front:GetLabel('My_label')" />:
</xsl:template>
</xsl:stylesheet>

When you run WSPBuilder it will automatically pick up the resx files and add them as embedded .resources files in the compiled dll.



Resource Assembly added: nb-NO\webparts.front.resources.dll

Monday, September 14, 2009

Early creation of public properties

I’m battling myself a bit about a public API I’m writing. Should I initialize all my public properties in the default constructor, or should I initialize them when accessed?

Having a public property returning null is not an option in my opinion as it leads to extra checking on the consumer of the API. Grunt work which the API should do for you.

Consider the two following classes:

public class MyClass
{
public List<string> List { get; set; }

public MyClass()
{
List = new List<string>();
}
}

and

public class MyClass
{
private List<string> _list;
public List<string> List
{
get
{
if( _list == null )
{
_list = new List<string>();
}
return _list;
}
set { _list = value; }
}

public MyClass()
{
}
}


The pros for the first class is that it’s short and very easy to read. The pros for the second class is that it is more optimized in terms of memory usage if the property is not always used.

My API has an object structure of about 20 classes, which may or may not be set. Some might be used more frequent and favor the first class, as others are infrequent and would favor the last one.

Having both implementations seems a bit inconsistent, so the big question is; should I favor the easy read, or the optimized? If the object structure is being created often, will creating all these extra objects be bad for the clr or doesn’t it matter?

It might be that benchmarking is the way to go to give the final answer, but any comments on the matter is appreciated.