by Mikael Henriksson
29. April 2009 11:32
First of all I’d like to thank Luca Passani for all his great work with wurfl. He’s done a good job. The database is updated at least once a month and the community I suppose has done a good job with the different API’s. I can however not use the .NET API’s. They are not thread safe and I thought I’d share with you how I improved the old .NET API.
I started of with renaming pretty much everything since the names did not talk to me. We can call the in-memory wurfldatabase the WurflHolder and the class to navigate the holder is called WurflNavigator. The implementation details was changed a bit as well since it did not give me the correct results but that is a different blog post. Why did I make it a Singleton class you ask? Well I tried with a static class first but it caused issues all over the planet. I had people getting detected with a completely wrong mobile phone. Also the logs was totally not right. It basically cause the whole application to go wrong. I though maybe this is a good place for the Singleton pattern and I was right. I am not sure my Singleton implementation is completely thread safe but it is sufficient for now.
Let’s start with the Singleton instance:
public class Singleton<T> where T : class, new()
{
protected Singleton()
{
}
public static T Instance
{
get { return SingletonCreator<T>.CreatorInstance; }
}
private sealed class SingletonCreator<S> where S : class, new()
{
private static readonly S instance = new S();
public static S CreatorInstance
{
get { return instance; }
}
}
}
I think the code speaks for itself. Basically if it’s not created I create it at runtime. The reason for making it generic is that I actually use it for two more classes. Then the API needs a couple of modifications, first in Global.asax we need to load the xml document:
Singleton<WurflHolder>.Instance.Load(HostingEnvironment.MapPath("/wurfl.xml"));
Then the default constructor for the Navigator needs to be changed to something like:
public WurlfNavigator()
{
try
{
_wurflFileNotLoaded = Singleton<WurflHolder>.Instance.WurflFileNotLoaded;
if (!Singleton<WurflHolder>.Instance.IsLoaded)
{
ThrowException(_wurflFileNotLoaded + ". Be sure that the creation of _wurfl have ran OK",
"prepareNavigatorModel");
}
_userAgentAndId = Singleton<WurflHolder>.Instance.UserAgentAndId;
_idAndFallback = Singleton<WurflHolder>.Instance.IdAndFallback;
_idAndCapabilities = Singleton<WurflHolder>.Instance.IdAndCapabilities;
_capabilityNames = Singleton<WurflHolder>.Instance.CapabilityNames;
}
catch (Exception ex)
{
ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
log.Error("WurlfNavigator", ex.InnerException);
}
}
This totally stops all randomness in the entire website. maybe not the best thing to keep it in memory but hey, it’s better than total unreliability!