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