views:

42

answers:

3

I wrote the following extension methods for Session so that I can persist and retrieve objects by their type. This works well for my solution, but I ended up having to duplicate my extension methods to cover the old HttpSessionState and the new HttpSessionStateBase. I'd like to find a way to get these back down to one set that covers both types. Any thoughts?

public static class SessionExtensions
{
    #region HttpSessionStateBase

    public static T Get<T>(this HttpSessionStateBase session)
    {
        return session.Get<T>(typeof(T).Name);
    }

    public static T Get<T>( this HttpSessionStateBase session, string key )
    {
        var obj = session[key];

        if( obj == null || typeof(T).IsAssignableFrom( obj.GetType() ) )
            return (T) obj;

        throw new Exception( "Type '" + typeof( T ).Name + "' doesn't match the type of the object retreived ('" + obj.GetType().Name + "')." );
    }

    public static void Put<T>(this HttpSessionStateBase session, T obj, string key)
    {
        session[key] = obj;
    }

    public static void Put<T>(this HttpSessionStateBase session, T obj)
    {
        session.Put(obj, typeof(T).Name);
    }

    #endregion

    #region HttpSessionState

    public static T Get<T>( this HttpSessionState session )
    {
        return session.Get<T>( typeof( T ).Name );
    }

    public static T Get<T>( this HttpSessionState session, string key )
    {
        var obj = session[ key ];

        if( obj == null || typeof( T ).IsAssignableFrom( obj.GetType() ) )
            return ( T ) obj;

        throw new Exception( "Type '" + typeof( T ).Name + "' doesn't match the type of the object retreived ('" + obj.GetType().Name + "')." );
    }

    public static void Put<T>( this HttpSessionState session, T obj )
    {
        session.Put( obj, typeof(T).Name );
    }

    public static void Put<T>( this HttpSessionState session, T obj, string key )
    {
        session[ key ] = obj;
    }

    #endregion
}
A: 

Unfortunately neither of those types have a common base class or interface you could use - for now you will have to duplicate the extension methods.

Andrew Hare
A: 

I found an answer that works but there are some drawbacks. I'm hoping someone will be able to improve upon it.

@Andrew Hare said that neither implement a common base or interface. Well, actually, they do. They both implement IEnumerable and ICollection. The question is, with that information in tow, do you want to create extension methods that extend IEnumerable or ICollection that are really only meant for Session? Maybe, maybe not. At any rate, here is a way to remove duplication with extension methods that extend HttpSessionState and HttpSessionStateBase simultaneously:

public static class SessionExtensions
{
    public static T Get<T>( this ICollection collection )
    {
        return collection.Get<T>( typeof( T ).Name );
    }

    public static T Get<T>( this ICollection collection, string key )
    {
        object obj = null;
        dynamic session = collection as HttpSessionState ?? ( dynamic ) ( collection as HttpSessionStateBase );

        if( session != null )
        {
            obj = session[key];

            if (obj != null && !typeof (T).IsAssignableFrom(obj.GetType()))
                throw new Exception("Type '" + typeof (T).Name + "' doesn't match the type of the object retreived ('" + obj.GetType().Name + "').");
        }

        return (T)obj;
    }

    public static void Put<T>( this ICollection collection, T obj )
    {
        collection.Put( obj, typeof( T ).Name );
    }

    public static void Put<T>( this ICollection collection, T obj, string key )
    {
        dynamic session = collection as HttpSessionState ?? ( dynamic ) ( collection as HttpSessionStateBase );
        if(session!=null)
            session[ key ] = obj;
    }
}

I'm not crazy about this solution, but it feels like a step, at least, in an interesting direction.

Byron Sommardahl
A: 

You could keep your initial implementation and use HttpSessionStateWrapper to handle the HttpSessionState case:

SomeType t = new HttpSessionStateWrapper(SomeHttpSessionStateInstance)
    .Get<SomeType>();
Darin Dimitrov