我的公司希望能够让我们的主网站加载少量WebForms页面,而无需重新编译网站。
起初我在想插件。所以我创建了一个小类,它有几个抽象的管家方法:
/// <summary>
/// ABC to support dynamic loading of Reports pages which inherit from this.
/// </summary>
public abstract class ReportsPageBase : System.Web.UI.Page
{
/// <summary>
/// Implement this to return the menu name of the page.
/// </summary>
/// <returns></returns>
public abstract string friendlyName();
}
其他开发人员将继承我班级的ASPX页面。他们的Web应用程序项目编译为DLL。那些/那些DLL被复制到我的插件子目录中。
在主网站中,当某个页面加载时,我扫描插件目录中的DLL,加载每个,获取它们的类型,过滤我的基类的支持并返回列表:
public static List<Testbed.ReportsPageBase.ReportsPageBase> loadDlls()
{
List<Testbed.ReportsPageBase.ReportsPageBase> retval = new List<ReportsPageBase.ReportsPageBase>();
string reportsDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins", "Reports");
if (!Directory.Exists(reportsDir))
{
try {Directory.CreateDirectory(reportsDir); }
Catch (Exception) { //Log the exception }
return retval;
}
string targetBaseTypeFullName = typeof(Testbed.ReportsPageBase.ReportsPageBase).FullName;
string[] filespecs = System.IO.Directory.GetFiles(reportsDir, "*.dll");
foreach (String filespec in filespecs)
{
Assembly ass = Assembly.LoadFrom(filespec);
Type[] tt = ass.GetTypes();
foreach (Type t in tt)
{
Type bt = t.BaseType;
if (bt == null) continue;
if (bt.FullName == targetBaseTypeFullName)
{
Testbed.ReportsPageBase.ReportsPageBase dynInstance = (Testbed.ReportsPageBase.ReportsPageBase)ass.CreateInstance(t.FullName, false);
if (dynInstance == null) continue;
retval.Add(dynInstance);
}
}
}
return retval;
}
我正在以集成模式定位IIS7。在web.config文件中,我设置了路由:
在Global.asax中,我选择将“RoutedReport.aspx”路由到我将在下面定义的RouteHandler:
public class Global : HttpApplication
{
// ...
void Application_Start(object sender, EventArgs e)
{
// ...
//http://msdn.microsoft.com/en-us/library/cc668202%28v=VS.90%29.aspx
System.Web.Routing.RouteTable.Routes.Add("MyRoutedRouteName", new Route("RoutedReport.aspx", new MyRouteHandler("~/AnythingCanGoHere.aspx")));
// ...
}
// ...
}
然后我根据MSDN建议声明一个IRouteHandler,根据上面添加的路由命名:
public class MyRouteHandler : System.Web.Routing.IRouteHandler
{
public MyRouteHandler(string virtualPath)
{
this.VirtualPath = virtualPath;
}
public string VirtualPath { get; private set; }
public IHttpHandler GetHttpHandler(System.Web.Routing.RequestContext requestContext)
{
// What now???
}
}
我可以使用其中一个动态加载的实例并返回它,因为页面继承自IHttpHandler。但是当我这样做时,什么都没有呈现。 我从哪里开始?