Autofac Webforms 可以忽略回发依赖注入
Autofac Webforms is there away to ignore postback dependency injection
我正在维护公司非常古老的网站 (WebForms),它使用 Autofac 作为依赖注入。
我遇到的一个问题是每次调用 Page_Load 时,都会再次解析所有依赖项,将它们设置为新的。我该如何阻止它?
现在手头没有代码,但这个例子应该能更好地解释
案例
public class DatabaseManager
{
public string CustomerDbConnection {get;set;}
}
public partial class SiteSetup: Page
{
public DatabaseManager dbManager {get;set;}
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// blah blah
}
}
protected void DdlDatabase_SelectedIndexChanged(object sender, EventArgs e)
{
dbManager.CustomerDbConnection = "Some db connection";
}
protected void ImageSaveSite_Click(object sender, EventArgs e)
{
// Do something with dbManager.CustomerDbConnection
}
}
所以在上面,DatabaseManager被注入到SiteSetup页面。当用户在下拉列表框 'DdlDatabase' 中选择一个项目时,设置 'dbManager.CustomerDbConnection'。
如果用户随后单击按钮 'ImageSaveSite',那么在尝试访问 'dbManager.CustomerDbConnection' 时出现异常,因为它为空。
在 'Page_OnLoad' 方法中放置一个断点,我可以看到每次调用它时我都可以看到 'dbManager.CustomerDbConnection' 为空。我只能假设正在解析 'DatabaseManager' 的新实例。
有什么办法可以避免这种情况吗?我正在考虑将 DatabaseManager 注册为单例,但网站的每个用户都不会访问同一个实例吗?
由于 WebForms 生命周期的工作方式,我推荐使用 ViewState
稍微不同的解决方案
如果你想在 postbacks 之间进行一些交流,你需要将它保存在 ViewState
中。但是连接不可序列化。所以我使用助手 属性 ConnectionIdentifier
来保持选定的标识符。
public string ConnectionIdentifier
{
get => ViewState[nameof(ConnectionIdentifier)] as string;
set => ViewState[nameof(ConnectionIdentifier)] = value;
}
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// blah blah
}
}
protected void DdlDatabase_SelectedIndexChanged(object sender, EventArgs e)
{
ConnectionIdentifier = "Selected db identifier";
}
protected void ImageSaveSite_Click(object sender, EventArgs e)
{
if(ConnectionIdentifier != null){
//not really needed depending on your UI
dbManager.CustomerDbConnection = ConnectionIdentifier; //processing identifier
}
}
我正在维护公司非常古老的网站 (WebForms),它使用 Autofac 作为依赖注入。
我遇到的一个问题是每次调用 Page_Load 时,都会再次解析所有依赖项,将它们设置为新的。我该如何阻止它?
现在手头没有代码,但这个例子应该能更好地解释
案例
public class DatabaseManager
{
public string CustomerDbConnection {get;set;}
}
public partial class SiteSetup: Page
{
public DatabaseManager dbManager {get;set;}
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// blah blah
}
}
protected void DdlDatabase_SelectedIndexChanged(object sender, EventArgs e)
{
dbManager.CustomerDbConnection = "Some db connection";
}
protected void ImageSaveSite_Click(object sender, EventArgs e)
{
// Do something with dbManager.CustomerDbConnection
}
}
所以在上面,DatabaseManager被注入到SiteSetup页面。当用户在下拉列表框 'DdlDatabase' 中选择一个项目时,设置 'dbManager.CustomerDbConnection'。
如果用户随后单击按钮 'ImageSaveSite',那么在尝试访问 'dbManager.CustomerDbConnection' 时出现异常,因为它为空。
在 'Page_OnLoad' 方法中放置一个断点,我可以看到每次调用它时我都可以看到 'dbManager.CustomerDbConnection' 为空。我只能假设正在解析 'DatabaseManager' 的新实例。
有什么办法可以避免这种情况吗?我正在考虑将 DatabaseManager 注册为单例,但网站的每个用户都不会访问同一个实例吗?
由于 WebForms 生命周期的工作方式,我推荐使用 ViewState
如果你想在 postbacks 之间进行一些交流,你需要将它保存在 ViewState
中。但是连接不可序列化。所以我使用助手 属性 ConnectionIdentifier
来保持选定的标识符。
public string ConnectionIdentifier
{
get => ViewState[nameof(ConnectionIdentifier)] as string;
set => ViewState[nameof(ConnectionIdentifier)] = value;
}
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// blah blah
}
}
protected void DdlDatabase_SelectedIndexChanged(object sender, EventArgs e)
{
ConnectionIdentifier = "Selected db identifier";
}
protected void ImageSaveSite_Click(object sender, EventArgs e)
{
if(ConnectionIdentifier != null){
//not really needed depending on your UI
dbManager.CustomerDbConnection = ConnectionIdentifier; //processing identifier
}
}