Opening Doors


</p>

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 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. 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.

Mocking Queryables