我正在组建一个网站,该网站从数据库中获取内容并将其填充到一个组件中,然后将其加载到页面上。问题是有许多不同的组件在编译时是未知的,我想从数据库中调用它们。
例如,可能有几个组件,例如:
- modContent.ascx
- modSlidingBanner.ascx
- modEmailSlug.ascx
数据库将包含一个表,其中包含定义要使用的模块和要加载到其中的内容的字段:
- 模块名称:“modContent”
- 内容:“zippidy doo da”
假设 modContent.ascx 看起来像:
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="modContent.ascx.cs" Inherits="modContent" %>
<div class="content">
<div class="content-wrapper" ID="divContentWrapper" runat="server">
<asp:Literal ID="litContent" runat="server"></asp:Literal>
</div>
</div>
并且 modContent.ascx.cs 包含方法:
public void FillIn(string html)
{
litContent.Text = html;
}
在我的主页上,我想加载这个控件并调用 FillIn 方法。如果我事先知道控件类型,我可以很容易地做到这一点:
modContent c = LoadControl("~/modContent.aspx");
c.FillIn(ContentFromDatabase);
divTargetPanel.Controls.Add(c);
但是,正如我提到的,我想根据数据库中的字符串选择几个控件之一。我可以保证这些控件中的每一个都会有 FillIn 方法。而且我想避免每次添加可能使用的新控件时必须有一个大的 switch 子句或我必须在主页上更改代码的东西。
我可以像这样将模块加载到页面上:
Control c = LoadControl("~/" + ControlNameFromDatabase + ".aspx");
divTargetPanel.Controls.Add(c);
但不能调用此控件的 FillIn 方法。
我可以将 FillIn 方法功能移动到 Control 的构造函数中并试试这个:
Assembly assembly = typeof(ControlsParentClass).Assembly;
Type type = assembly.GetType(ControlNameFromDatabase);
skinHome.divContentPanel.Controls.Add(LoadControl(type, new object[] { ContentFromDatabase }));
但是,这会出错,因为 litContent
在 modContent.ascx.cs 中返回 null
,如 this guy's question 中所述.
显然上面描述的控件非常简单。我已经把它精简到最基本的部分。这些模块实际上会复杂得多,每个模块都有自己的结构和代码,但具有相同的方法名称/参数。
我这样做是不是完全错误了?
最佳答案
声明一个 interface包含您所有的公共(public)方法和属性
public interface IMyControl
{
void FillIn(string html);
}
从此界面继承所有控件:
public partial class modContent : Control, IMyControl
将所有控件转换到 IMyControl
并调用 FillIn
IMyControl c = LoadControl("~/modContent.aspx") as IMyControl;
c.FillIn(ContentFromDatabase);
divTargetPanel.Controls.Add(c as Control);
关于c# - 动态添加未知类型的控件并在控件上调用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16320557/