Castle.Windsor и объект доступа к данным с помощью webforms asp.net - PullRequest
0 голосов
/ 20 июня 2011

Я создал пример проекта, опробующего несколько новых шаблонов, а именно Dao и IoC.

Мой Дао определяется следующим образом:

public class Dao<T> : IDao<T>
{
    protected NHibernate.ISessionFactory _sessionFactory;

    public Dao(NHibernate.ISessionFactory sessionFactory)
    {
        this._sessionFactory = sessionFactory;
    }

    protected NHibernate.ISession Session
    {
        get { return _sessionFactory.GetCurrentSession(); }
    }

    public T GetById(object id)
    {
        return Session.Get<T>(id);
    }

    ...
}

А у меня есть соответствующий установщик:

public class DaoInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Component.For(typeof(Data.IDao<>))
            .ImplementedBy(typeof(Data.Dao<>))
            .ServiceOverrides(ServiceOverride.ForKey("SessionFactory").Eq("FirstSessionFactory"))
            .Named("FirstDao"));
    }
}

Используя шаблон MVC, я могу определить контроллер с конструктором, который будет принимать IDao<MyClass> myClass в качестве аргумента, и Виндзор сделает всю магию создания Dao с правильным SessionFactory для меня. У меня вопрос, как мне добиться того же поведения в среде, отличной от MVC? Итак, на какой конкретной странице я могу получить экземпляр myClass?

Ответы [ 2 ]

2 голосов
/ 21 июня 2011

До MVC ASP.Net не был создан для использования шаблонов IoC.MVC поддерживает IoC, и существуют точки расширения, где Windsor и другие реализации IoC могут подключаться к инфраструктуре MVC, чтобы взять на себя задачу создания полностью сконфигурированных контроллеров с заводов MVC по умолчанию.На сайте веб-форм нет такого средства, которое бы создавало для вас классы страниц.

Использование NHibernate в проекте веб-форм предполагает использование коллекции Items HttpRequest и, как правило, модуля HttpModule, который будет выполнять код до ипосле того, как запрос обработан классом Page.В начале запроса модуль создает сеанс NHibernate и помещает его в коллекцию Items запроса (единственное место, где вы можете поместить его в ASP.Net).Затем код на странице можно получить на сессии.Классы страниц будут создавать реализацию IDao по мере необходимости и передавать в нее сеанс.В конце запроса код в модуле сбрасывает и закрывает сеанс.Таким образом, все управление сессиями прозрачно обрабатывается кодом в обработчике страницы.(Это то, что я делал до перехода на MVC и инфраструктуру Sharp Architecture. Было очень много инфраструктурного кода, который было трудно получить правильно; теперь я рад использовать Sharp Architecture. Он хорошо продуман и имеет больше глазглядя на него, а не только на меня.)

Вы все еще можете использовать контейнер IoC в проекте веб-форм, но он не полностью прозрачен.Вы можете явно попросить ваш контейнер для реализации IDao.Вам потребуется настроить контейнер IoC, чтобы обеспечить реализацию ISession для реализации IDao, и настроить его для управления временем жизни сеанса с семантикой каждого веб-запроса.Но он не так чист, как в MVC, где нет кода для контроллера.

0 голосов
/ 22 июня 2011

Спасибо за ваши ответы.К сожалению, потому что я настолько новичок в этой области (с очень ограниченным временем в моих руках), я теперь еще больше смущен, чем был раньше.Из того, что я понял, веб-формы не предназначены для использования с IoC, и хотя существуют обходные пути, они довольно сложны.Я думаю, что откажусь от Windsor, пока не перенесу проект в MVC, сейчас я использовал простой статический SessionManager класс.

Затем SessionManager отвечает за создание экземпляра SessionFactoriesContainer во время App_Init, определяемого как:

public static readonly Dictionary<string, ISessionFactory> SessionFactoriesContainer = new Dictionary<string, ISessionFactory>();

и SessionsContainer определены как:

public static Dictionary<string, ISession> SessionsContainer
    {
        get
        {
            Dictionary<string, ISession> sessionContainer = (Dictionary<string, ISession>)HttpContext.Current.Items[SESSION_CONTAINER_KEY] ?? new Dictionary<string, ISession>();
            foreach (FactoryType type in Enum.GetValues(typeof(FactoryType)))
            {
                if (!sessionContainer.ContainsKey(type.ToString()))
                    sessionContainer.Add(type.ToString(), null);
            }
            HttpContext.Current.Items[SESSION_CONTAINER_KEY] = sessionContainer;
            return sessionContainer;
        }
    }

Хотя SessionsContainer является статическим, поскольку он хранится в HttpContext, я понимаю, что у каждого пользователя будет свой контейнер, я не правпредполагая это?

SessionManager также имеет класс GetSessionFor, определенный как:

public static ISession GetSessionFor(FactoryType type)
    {
        ISession session = SessionsContainer[type.ToString()] ?? SessionFactoriesContainer[type.ToString()].OpenSession();
        session.BeginTransaction();
        SessionsContainer[type.ToString()] = session;

        return session;
    }

Этот метод вызывается всякий раз, когда требуется новый репозиторий, и ISession затем передается конструктору.В конце запроса каждый открытый сеанс будет либо зафиксирован, либо транзакция будет откатана в случае ошибок.

Я понимаю, что это очень грубая реализация, но я думаю, что она должна работать.Если у меня будет время в конце проекта, я собираюсь вернуться к управлению сессиями и, надеюсь, внедрить установщики.В то же время, если у кого-то есть еще идеи, пожалуйста, не стесняйтесь их добавлять.

...