![](/img/trans.png)
[英]asp.net within a hosted environment and Castle.Windsor -> Required permissions cannot be acquired
[英]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.