在 C# 中动态转换 Page.LoadControl
本文关键字:Page LoadControl 转换 动态 | 更新日期: 2023-09-27 18:30:23
我是第一次编写一些用户控件,我想知道是否有办法清理我的一些代码。(如果您想了解更多有关我正在做的事情的背景信息,请参阅此问题。
我有一个BaseControl
类,它基本上解析一些 XML 数据,然后根据该数据中包含的内容,调用相应的UserControl
并发送数据。 下面是一个示例:
public partial class BaseControl : User Control
{
protected void Page_Load(object sender, EventArgs e)
{
... //code that parses the data
var renewalDef = effort.Attributes["renewal_def"].Value;
var effortNumber = effort.Attributes["renewal_effort_number"].Value;
if (effortNumber == "1")
{
var effortControl = (NAVLEffort1) Page.LoadControl("~/NAVLSeriesControls/NAVLEffort1.ascx");
effortControl.transactionData = transaction; //'transaction' is a Hashtable object
HtmlContent.Controls.Add(effortControl); //'HtmlContent' is a PlaceHolder control on BaseControl.ascx page
}
if (effortNumber == "2")
{
var effortControl = (NAVLEffort2) Page.LoadControl("~/NAVLSeriesControls/NAVLEffort2.ascx");
effortControl.transactionData = transaction; //'transaction' is a Hashtable object
HtmlContent.Controls.Add(effortControl); //'HtmlContent' is a PlaceHolder control on BaseControl.ascx page
}
if (effortNumber == "3")
{
var effortControl = (NAVLEffort3) Page.LoadControl("~/NAVLSeriesControls/NAVLEffort3.ascx");
effortControl.transactionData = transaction; //'transaction' is a Hashtable object
HtmlContent.Controls.Add(effortControl); //'HtmlContent' is a PlaceHolder control on BaseControl.ascx page
}
// and so on...
}
}
这不是我编写的实际代码,它只是我可能走向何方的一个例子。 我想做的是更像这样的事情:
...
var effortControlFileString = string.Format("~/NAVLSeriesControls/{0}Effort{1}.ascx", renewalDef, effortNumber);
var effortControl = (renewalDef + "Effort" + effortNumber) Page.LoadControl(effortControlFileString);
effortControl.transactionData = transaction;
HtmlContent.Controls.Add(effortControl)
...
任何想法如何清理这个烂摊子?
接口
可以让所有控件实现一个通用接口并强制转换为该接口。
public interface IMyInterface
{
object TransactionData
{
get;
set;
}
}
Control effortControl = Page.LoadControl(path);
HtmlContent.Controls.Add(effortControl);
IMyInterface obj = (IMyInterface)effortControl;
obj.TransactionData = transaction;
请参阅联机 IDE 中的此工作示例。
基类
还可以使用抽象基类并强制转换为具有相同结果的类型。您将需要使用继承自UserControl
的基类。这将避免有两个对象引用(如我上面的例子),因为它可以转换为UserControl
。
上面的示例变为:
MyCustomControlType c = (MyCustomControlType)Page.LoadControl(path);
HtmlContent.Controls.Add(c);
c.TransactionData = transaction;
如果每个控件类型的逻辑不同,则可能需要强制转换为每个特定类型(基本上是一个大的 if/else 块)并单独处理每个控件。换句话说,如果需要根据控件的类型执行不同的操作,则需要类型感知的逻辑。
为了完整起见,我会提到你也可以使用 DLR,但我建议不要这样做。您将放弃编译时类型的安全性和性能来减少少量代码。
您可以创建一个接口并将控件添加到 HTML 页面。前任:
private Control _contentControl;
_contentControl = Page.LoadControl("~/Administration/Projects/UserControls/" + controlName);
((IEditProjectControl)_contentControl).ProjectId = ProjectId;
plhContent.Controls.Clear();
plhContent.Controls.Add( _contentControl );
_contentControl.ID = "ctlContent";
Image2.Visible = ((IEditProjectControl)_contentControl).ShowSaveButton;
SaveButton.Visible = ((IEditProjectControl)_contentControl).ShowSaveButton;
((IEditProjectControl)_contentControl).Initialize();