我正在尝试在运行时找到页面请求的程序集。我使用了Get current System.Web.UI.Page from HttpContext?的代码,它适用于大多数呼叫,但存在问题。
如果在我的aspx.cs中,我在类HttpContext.Current.CurrentHandler
顶部实例化一个类变量为null。
示例
我有一个名为Business.dll
的DLL,其功能是根据上述SO问题获取Page类型。
在我的页面中,FrontEnd.dll
中的default.asp我有以下呼叫:
public partial class FrontEnd: Page
{
private readonly Type _t = Business.GetPageType();
上面的代码将HttpContext.Current.CurrentHandler作为null返回,HttpContext.Current.ApplicationInstance返回HttpApplication作为类型,因此将System.Web作为程序集返回。
如果我这样写:
public partial class FrontEnd: Page
{
readonly Type _t;
protected override void OnInit(EventArgs e)
{
_t = Business.GetPageType();
它运行得很好,我得到了对CurrentHandler和页面的引用。我当然可以重构所有地方并将变量初始化移动到OnInit,但这需要在应用程序中使用约定并且维护程度更高。
使用Assembly.GetEntryAssembly()
为示例返回null,Assembly.GetExecutingAssembly()
返回Business.dll,所以我也不能使用它们。
是否有其他方法可以找到类型/ dll,也许使用请求网址来查找它来自的类型/ dll?
[更新]
到目前为止,我有这个代码,因为我的所有dll都使用已知密钥签名(不包括检查签名密钥的额外方法):
StackTrace stackTrace = new StackTrace();
StackFrame[] stackFrames = stackTrace.GetFrames();
Assembly firstAssembly = null;
foreach (StackFrame stackFrame in stackFrames)
{
var method = stackFrame.GetMethod();
Type t = method.DeclaringType;
if (t != null && t.Assembly.Is(SignedBy.Me))
{
firstAssembly = t.Assembly;
}
}
if( firstPzlAssembly != null)
{
return firstPzlAssembly;
}
虽然它有效但看起来不对,如果经常打电话会有潜在的性能损失。
答案 0 :(得分:2)
当你这样做时:
private readonly Type _t = Business.GetPageType();
它实际上被编译为构造函数中的字段初始化。 这意味着对象(您的页面)尚未构建。它还不存在,它正在“诞生”。在这个阶段,你只是在构造函数中。
在构造对象(页面)之前,ASP.NET基础结构无法将其分配给HttpContext.Current.CurrentHandler静态属性。好吧,因为处理程序(你的页面)还不存在而且正在构造id。
所以你不能做你想做的事。
你可以做的是创建一个PageBase类,重写OnInit方法并在那里添加这段代码:
public abstract class PageBase
{
protected Type PageType { get; private set; }
protected override void OnInit(EventArgs e)
{
PageType = Business.GetPageType();
}
}
现在只是从这个基类派生你的页面:
public partial class FrontEnd: PageBase { .... }
(或者直接在ASPX文件中将PageBase指定为基类,无论你做什么。
答案 1 :(得分:0)
一个选项是定义一个基页,根据需要设置OnInit函数,然后确保所有其他页继承自该页。
例如:
public class CustomBasePage: Page
{
readonly Type _t;
protected override void OnInit(EventArgs e)
{
_t = Business.GetPageType();
}
}
然后将所有页面改为继承而不是正常的Page
类:
public partial class FrontEnd: CustomBasePage
这意味着您只需要定义一次逻辑并在其余应用程序页面上放置最小的开销。
如果任何页面由于其他原因需要覆盖OnInit
,则只需要包含对base.OnInit();
的调用,这不会太繁琐。
您需要确保Business.GetPageType();
返回您的期望。我不清楚它到底在做什么以及它是否会返回FrontEnd
或CustomBasePage
类,(或者你的应用程序逻辑可以接受哪些类)。