Opening Doors

joshka left a comment on my previous post that reads…

"… Can you talk about the Application Context and IKey stuff a little in a future post?"

The IKey<T> interface defines a contract for different keys that are put into a dictionary. It depends on the implementation of the key to know how to parse its value out of the dictionary.

public interface IKey<T>
{
    bool is_found_in(IDictionary items);
    T parse_from(IDictionary items);
    void remove_from(IDictionary items);
    void add_value_to(IDictionary items, T value);
}

An implementation of the key that we used for shoving an ISession into the HttpContext.Items collection is the TypedKey<T>. It creates a unique key based on type T.

internal class TypedKey<T> : IKey<T>
{
    public bool is_found_in(IDictionary items)
    {
        return items.Contains(create_unique_key());
    }

    public T parse_from(IDictionary items)
    {
        return (T) items[create_unique_key()];
    }

    public void remove_from(IDictionary items)
    {
        if (is_found_in(items))
        {
            items.Remove(create_unique_key());
        }
    }

    public void add_value_to(IDictionary items, T value)
    {
        items[create_unique_key()] = value;
    }

    public bool Equals(TypedKey<T> obj)
    {
        return !ReferenceEquals(null, obj);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != typeof (TypedKey<T>)) return false;
        return Equals((TypedKey<T>) obj);
    }

    public override int GetHashCode()
    {
        return GetType().GetHashCode();
    }

    private string create_unique_key()
    {
        return GetType().FullName;
    }
}

It knows how to add a value in to the dictionary using it as the key, and how to parse values from the dictionary using it. The application context can be an adapter around the HttpContext, or a hand rolled context for win forms. An implementation on the web might look like….

public class WebContext : IApplicationContext
{
    public bool contains<T>(IKey<T> key)
    {
        return key.is_found_in(HttpContext.Current.Items);
    }

    public void add<T>(IKey<T> key, T value)
    {
        key.add_value_to(HttpContext.Current.Items, value);
    }

    public T get_value_for<T>(IKey<T> key)
    {
        return key.parse_from(HttpContext.Current.Items);
    }

    public void remove(IKey<ISession> key)
    {
        key.remove_from(HttpContext.Current.Items);
    }
}

When running your integration tests, you can swap out the implementation with an implementation specific to running unit tests.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Mo Khan

mO, is just a kid who's excited about writing software. He's a student of his profession, and just wants to share his thoughts on software development.
This entry was posted in Design Patterns. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

2 Responses to Opening Doors

  1. Jonathan says:

    I do the same thing and have an implementation for HttpContext as well as thread local storage (if it’s not a web app):

    var slot = Thread.GetNamedDataSlot(slotName);
    var content = (T)Thread.GetData(slot);

  2. Mo says:

    That’s an awesome use for thread local storage. Thanks Jonathan!