Как я могу написать расширения для Session без необходимости писать отдельные методы для HttpSessionState и HttpSessionStateBase? - PullRequest
6 голосов
/ 19 июня 2010

Я написал следующие методы расширения для Session, чтобы я мог сохранять и извлекать объекты по их типу. Это хорошо работает для моего решения, но мне пришлось дублировать мои методы расширения, чтобы покрыть старый HttpSessionState и новый HttpSessionStateBase. Я хотел бы найти способ вернуть их обратно к одному набору, который охватывает оба типа. Есть мысли?

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
}

Ответы [ 3 ]

3 голосов
/ 19 июня 2010

Вы можете сохранить первоначальную реализацию и использовать HttpSessionStateWrapper для обработки случая HttpSessionState:

SomeType t = new HttpSessionStateWrapper(SomeHttpSessionStateInstance)
    .Get<SomeType>();
2 голосов
/ 19 июня 2010

Я нашел ответ, который работает, но есть некоторые недостатки. Я надеюсь, что кто-то сможет улучшить это.

@ Эндрю Хэйр сказал, что ни реализует общую базу, ни интерфейс. Ну, на самом деле, они делают. Они оба реализуют IEnumerable и ICollection. Вопрос в том, что с этой информацией в буксировке, вы хотите создать методы расширения, которые расширяют IEnumerable или ICollection, которые действительно предназначены только для Session? Может быть, а может и нет. В любом случае, вот способ удалить дублирование с помощью методов расширения, которые расширяют HttpSessionState и HttpSessionStateBase одновременно:

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;
    }
}

Я не в восторге от этого решения, но это похоже на шаг, по крайней мере, в интересном направлении.

1 голос
/ 19 июня 2010

К сожалению, ни один из этих типов не имеет общего базового класса или интерфейса, который вы могли бы использовать - сейчас вам придется дублировать методы расширения.

...