簡體   English   中英

使用webforms asp.net的Castle.Windsor和數據訪問對象

[英]Castle.Windsor and data access object with webforms asp.net

我創建了一個示例項目,試用了一些新的模式,即Dao和IoC。

我的Dao定義如下:

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作為參數,而Windsor將為我實現使用正確的SessionFactory實例化Dao的所有魔力。 我的問題是,如何在非MVC環境中實現相同的行為? 所以在任何特定的頁面上,我如何獲得myClass的實例?

在MVC之前,ASP.Net不是為了使用IoC模式而構建的。 MVC是IoC意識的,並且有一些擴展點,Windsor和其他IoC實現可以插入到MVC框架中,以接管從MVC的默認工廠實例化完全配置的控制器的任務。 Web表單站點中沒有可以為您實例化頁面類的工具。

在Web表單項目中使用NHibernate涉及使用HttpRequest的Items集合,通常是一個HttpModule,它將在Page類處理請求之前和之后執行代碼。 在請求開始時,模塊創建一個NHibernate會話並將其放入請求的Items集合中(您可以將它放在ASP.Net上的唯一位置)。 然后頁面上的代碼可以進入會話。 頁面類將根據需要實例化IDao實現,並將會話傳遞給它。 在請求結束時,模塊中的代碼將刷新並關閉會話。 這樣,所有會話管理都透明地處理頁面處理程序中的代碼。 (這是我在切換到MVC和Sharp Architecture框架之前所做的。很多基礎設施代碼很難做到正確;我很高興現在使用Sharp Architecture。它經過深思熟慮,有更多的眼睛看着它而不僅僅是我的。)

您仍然可以在Web表單項目中使用IoC容器,但它並不完全透明。 您可以明確地向容器詢問IDao的實現。 您必須配置IoC容器以向IDao實現提供ISession實現,並將其配置為使用每Web請求語義管理會話生存期。 但它並不像MVC那樣干凈,因為MVC中沒有代碼。

謝謝您的回答。 不幸的是因為我對這個領域很陌生(手上的時間非常有限),我現在比以前更加困惑。 根據我的理解,webforms並不意味着與IoC一起使用,雖然存在解決方法,但它們相當復雜。 我想在將項目遷移到MVC之前我將放棄Windsor,現在我已經使用了一個簡單的靜態SessionManager類。

然后,SessionManager負責在App_Init期間實例化SessionFactoriesContainer ,定義如下:

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傳遞給構造函數,就會調用此方法。 在請求結束時,每個打開的會話都將被提交,或者在發生錯誤時將回滾事務。

我意識到這是一個非常粗略的實現,但我認為它應該工作。 如果我在項目結束時有時間,我的目標是重新訪問會話管理,並希望實現安裝程序。 在此期間,如果任何人有任何想法,請隨時添加它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM