<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>caliberweb.com &#187; LocalData</title>
	<atom:link href="http://chris.caliberweb.com/tags/localdata/feed/" rel="self" type="application/rss+xml" />
	<link>http://chris.caliberweb.com</link>
	<description></description>
	<lastBuildDate>Mon, 01 Jun 2009 22:35:33 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>ILocalData Again</title>
		<link>http://chris.caliberweb.com/2009/02/19/ilocaldata-again/</link>
		<comments>http://chris.caliberweb.com/2009/02/19/ilocaldata-again/#comments</comments>
		<pubDate>Thu, 19 Feb 2009 15:14:46 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Ah-Hah]]></category>
		<category><![CDATA[Isolation]]></category>
		<category><![CDATA[LocalData]]></category>

		<guid isPermaLink="false">http://chris.caliberweb.com/2009/02/19/ilocaldata-again/</guid>
		<description><![CDATA[Just a random ‘ah-hah’ momentary update on the last post.
EDIT: After further refactoring, I’m done&#8230;.for now. 
You can download the code here.
]]></description>
			<content:encoded><![CDATA[<p>Just a random ‘ah-hah’ momentary update on the <a href="http://chris.caliberweb.com/2009/02/18/cool-ilocaldata-implementation/" target="_blank">last post</a>.</p>
<p><em>EDIT: After further refactoring, I’m done&#8230;.for now. </em></p>
<p><em>You can download the code <a href="http://chris.caliberweb.com/wp-content/uploads/2009/02/caliberweblocaldata.zip">here</a>.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://chris.caliberweb.com/2009/02/19/ilocaldata-again/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Cool ILocalData Implementation</title>
		<link>http://chris.caliberweb.com/2009/02/18/cool-ilocaldata-implementation/</link>
		<comments>http://chris.caliberweb.com/2009/02/18/cool-ilocaldata-implementation/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 22:01:22 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Isolation]]></category>
		<category><![CDATA[LocalData]]></category>

		<guid isPermaLink="false">http://chris.caliberweb.com/?p=11</guid>
		<description><![CDATA[I’ve always been impressed with Ayende’s LocalData class. I like Ritesh Rao’s vision of local data even more. I loved how he gives the option of application, session, and thread storage. But, I feel like those implementations leave something to be desired from a consumers perspective. So, I’ve come up with a base interface that [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve always been impressed with <a href="http://ayende.com" target="_blank">Ayende</a>’s <a href="https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk/commons/Rhino.Commons.Clr/LocalDataImpl/" target="_blank">LocalData</a> class. I like <a href="http://www.codeinsanity.com" target="_blank">Ritesh Rao’s</a> vision of <a href="http://www.codeplex.com/ncommon/SourceControl/changeset/view/31331#367939" target="_blank">local data</a> even more. I loved how he gives the option of application, session, and thread storage. But, I feel like those implementations leave something to be desired from a consumers perspective. So, I’ve come up with a base interface that is inspired by both of the above projects. It also defines an abstract class so I can create new implementations whenever I need to.</p>
<p><em>The ILocalData interface:</em></p>
<pre class="brush: csharp">
public interface ILocalData
{
    object this[object key] { get; set; }
    T Get(object key);
    bool TryGet(object key, out T value);
    T Set(object key, T value);
    void Add(object key, object value);
    void Remove(object key);
    void Remove(params object[] keys);
    bool Contains(object key);
    void Clear();
}
</pre>
<p>The IDataBucket interface:</p>
<pre class="brush: csharp">
public interface IDataBucket : IEnumerable
{
    object this[object key] { get; set; }
    bool ContainsKey(object key);
    void Remove(object key);
    void Clear();
    void Add(object key, object value);
    bool UseSynchLock { get; set; }
}
</pre>
<p>The entry point and abstract class:</p>
<pre class="brush: csharp">
public class LocalData : BucketData
{
    public LocalData(IDataBucket bucket)
        : base(bucket)
    {}

    public LocalData(Func&lt;IDataBucket&gt; bucketProvider)
        : base(bucketProvider)
    {}
}

public abstract class BucketData : ILocalData, IEnumerable
{
    private static readonly object lockInstance = new object();
    private readonly Func&lt;IDataBucket&gt; bucketProvider;

    protected BucketData(IDataBucket bucket)
        : this(() =&gt; bucket)
    {}

    protected BucketData(Func&lt;IDataBucket&gt; bucketProvider)
    {
        this.bucketProvider = bucketProvider;
    }

    public IDataBucket Bucket
    {
        get { return bucketProvider(); }
    }

    public object this[object key]
    {
        get { return Do(() =&gt; Bucket[key.ToString()]); }
        set { Do(() =&gt; Bucket[key.ToString()] = value); }
    }

    public IEnumerator GetEnumerator()
    {
        return Bucket.GetEnumerator();
    }

    public T Get&lt;T&gt;(object key)
    {
        return Do(() =&gt;
                      {
                          T value;
                          TryGet(key, out value);
                          return value;
                      });
    }

    public bool TryGet&lt;T&gt;(object key, out T value)
    {
        value = default(T);
        object data = Bucket[key.ToString()];

        if (data == null)
            return false;

        if (data is T)
        {
            value = (T) data;
            return true;
        }

        return false;
    }

    public T Set&lt;T&gt;(object key, T value)
    {
        return Do(() =&gt;
                      {
                          Bucket[key.ToString()] = value;
                          return value;
                      });
    }

    public void Add(object key, object value)
    {
        Set(key, value);
    }

    public void Remove(object key)
    {
        if (Contains(key))
            Do(() =&gt; Bucket.Remove(key.ToString()));
    }

    public void Remove(params object[] keys)
    {
        foreach (object key in keys)
        {
            Remove(key);
        }
    }

    public bool Contains(object key)
    {
        return Do(() =&gt; Bucket[key.ToString()] != null);
    }

    public void Clear()
    {
        Do(() =&gt; Bucket.Clear());
    }

    private V Do&lt;V&gt;(Func&lt;V&gt; function)
    {
        if (Bucket.UseSynchLock)
        {
            lock (lockInstance)
            {
                return function();
            }
        }

        return function();
    }

    private void Do(Action action)
    {
        if (Bucket.UseSynchLock)
        {
            lock (lockInstance)
            {
                action();
            }
        }

        action();
    }
}
</pre>
<p>With the following, I can finally say goodbye to buggy HttpSessionState code in legacy systems and even support session isolation.</p>
<pre class="brush: csharp">
public class HttpSessionDataBucket : IDataBucket
{
    private readonly string bucketName;

    public HttpSessionDataBucket() : this(typeof (IDataBucket))
    {}

    public HttpSessionDataBucket(Type forType) : this(forType.FullName)
    {}

    public HttpSessionDataBucket(string bucketName)
    {
        this.bucketName = bucketName;
    }

    private Hashtable Bucket
    {
        get
        {
            HttpSessionState session = HttpContext.Current.Session;
            object ht = session[bucketName];

            if (ht is HashtableDataBucket)
                return (Hashtable) ht;

            session[bucketName] = ht = new Hashtable();

            return ht as Hashtable;
        }
    }

    public object this[object key]
    {
        get { return Bucket[key.ToString()]; }
        set { Bucket[key.ToString()] = value; }
    }

    public bool ContainsKey(object key)
    {
        return Bucket[key.ToString()] != null;
    }

...
}
ILocalData localData = new LocalData(new HttpSessionDataBucket(typeof(IMenuItem)));
</pre>
<p>This is obviously still evolving but, for now, I love being able to have an ILocalData instance in my domain objects (most likely not session buckets though) and being able to call “localData.Clear();” without messing up the rest of the system.</p>
<p>It’s amazing how far we’ll go sometimes. Schwew! <img src='http://chris.caliberweb.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>-=Code Well</p>
]]></content:encoded>
			<wfw:commentRss>http://chris.caliberweb.com/2009/02/18/cool-ilocaldata-implementation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
