2011-06-20 29 views
0

我已經創建了一個示例項目,嘗試一些新的模式,即Dao和IoC。Castle.Windsor和Webforms的數據訪問對象asp.net

吾道定義如下:

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的實例?

+0

你可能會發現[這個答案](http://stackoverflow.com/questions/293790/how-to-use-castle-windsor-with-asp-net-web-forms)有用。 –

回答

2

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

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

您仍然可以在Web窗體項目中使用IoC容器,但它不完全透明。您可以明確要求您的容器實施IDao。您必須配置IoC容器以將ISession實現提供給IDao實現,並將其配置爲使用每個Web請求語義來管理會話生存期。但它並不像在MVC中那樣乾淨,在這裏沒有控制器中的代碼。

+0

您能否提供一些關於DI如何「模擬」的代碼示例?目前,我只能想到在需要的頁面上從HttpContext中檢索所需的會話,但在這種情況下,Windsor只是一個插件,並不是絕對必要的。 – Shagglez

+0

Krzysztof答案中的鏈接看起來很有趣。從Windsor網站上的搜索,我發現它有一個HttpModule在網絡應用程序中使用NHibernate:http://www.castleproject.org/container/facilities/trunk/nhibernate/webapp.html。 –

0

謝謝你的回答。不幸的是,因爲我對這個領域非常陌生(我手上的時間非常有限),我現在比以前更加困惑。根據我的理解,webforms並不意味着與IoC一起使用,儘管存在解決方法,但它們相當複雜。 我想我會放棄溫莎,直到我將項目遷移到MVC,現在我已經利用了一個簡單的靜態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傳遞給構造函數調用。在請求結束時,每個打開的會話都將被提交,或者在發生錯誤時將事務回滾。

我意識到這是一個非常粗糙的實現,但我認爲它應該工作。如果我在項目結束時有時間,我的目標是重新審視會議管理並希望實施安裝人員。同時,如果任何人有更多的想法,請隨時添加它們。