简体   繁体   English

从当前上下文中查找页面或页面程序集

[英]Finding Page or Page assembly from current context

I'm trying to find the assembly of a page request during runtime. 我正试图在运行时找到页面请求的程序集。 I have used the code at Get current System.Web.UI.Page from HttpContext? 我在HttpContext中使用Get current System.Web.UI.Page中的代码 which work for most calls, but there is an issue. 适用于大多数电话,但存在问题。

If in my aspx.cs I instantiate a class variable at the top of my class HttpContext.Current.CurrentHandler is null. 如果在我的aspx.cs中,我在类的顶部实例化一个类变量HttpContext.Current.CurrentHandler为null。

Example
I have one DLL named Business.dll with the function to get the Page type as per the above SO question. 我有一个名为Business.dll DLL,其功能是根据上述SO问题获取Page类型。

In my page, default.asp in FrontEnd.dll I have the following call: 在我的页面中, FrontEnd.dll default.asp我有以下调用:

public partial class FrontEnd: Page
{
   private readonly Type _t = Business.GetPageType();

The above code return HttpContext.Current.CurrentHandler as null and HttpContext.Current.ApplicationInstance return HttpApplication as the type, and hence System.Web as the assembly. 上面的代码返回HttpContext.Current.CurrentHandler为null,HttpContext.Current.ApplicationInstance返回HttpApplication作为类型,因此System.Web作为程序集返回。

If I however write it like this: 如果我这样写:

public partial class FrontEnd: Page
{
   readonly Type _t;

   protected override void OnInit(EventArgs e)
   {
      _t = Business.GetPageType();    

it works just fine, and I get a reference to CurrentHandler and the page. 它工作得很好,我得到了CurrentHandler和页面的引用。 I could of course refactor all places and move the variable initialization to OnInit, but this requires convention in the app and a higher degree of maintenance. 我当然可以重构所有地方并将变量初始化移动到OnInit,但这需要在应用程序中使用约定和更高程度的维护。

Using Assembly.GetEntryAssembly() return null for the example and Assembly.GetExecutingAssembly() return Business.dll, so I cannot use them either. 使用Assembly.GetEntryAssembly()为示例返回null,而Assembly.GetExecutingAssembly()返回Business.dll,所以我也不能使用它们。

Is there possible another way to find the type/dll, perhaps using the Request Url to find the type/dll which it originates from? 有没有其他方法可以找到类型/ dll,可能使用请求URL来查找它来自的类型/ dll?

[Update] [更新]
So far I have this code, as all my dll's are signed with a known key (not including the extra methods for checking the signing key): 到目前为止,我有这个代码,因为我的所有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;
}

While it works, it seems wrong and will have a potential performance hit if called often. 虽然它有效,但它似乎是错误的,如果经常打电话会有潜在的性能损失。

When you do it this way: 当你这样做时:

private readonly Type _t = Business.GetPageType();

it is actually compiled into a field initialization within the constructor . 它实际上被编译成构造函数中的字段初始化。 It means that the object (your page) is not constructed yet . 这意味着对象(您的页面) 尚未构建 It does not exist yet, it is "being born". 它还不存在,它正在“诞生”。 You are just within the constructor at this stage. 在这个阶段你就在构造函数中。

Until your object (the page) is constructed, ASP.NET infrastructure cannot assign it to an HttpContext.Current.CurrentHandler static property. 在构建对象(页面)之前,ASP.NET基础结构无法将其分配给HttpContext.Current.CurrentHandler静态属性。 Well, because the handler (your page) does not exist yet and id being constructed. 好吧,因为处理程序(你的页面)还不存在而且正在构造id。

So you cannot do what you want. 所以你不能做你想做的事。

What you can do is to create a PageBase class, override OnInit method and add this code there: 你可以做的是创建一个PageBase类,重写OnInit方法并在那里添加以下代码:

public abstract class PageBase
{
     protected Type PageType { get; private set; }

     protected override void OnInit(EventArgs e)
     {
        PageType = Business.GetPageType();
     } 
}

and now just derive your pages from this base class: 现在只从这个基类派生你的页面:

public partial class FrontEnd: PageBase { .... }

(or specify PageBase as a base class directly in ASPX file, whatever you do. (或者直接在ASPX文件中将PageBase指定为基类,无论你做什么。

One option, is to define a single base page, with the OnInit function setup as required, and then ensure that all your other pages inherit from that. 一种选择是定义单个基页,根据需要设置OnInit函数,然后确保所有其他页继承自该页。

For example: 例如:

public class CustomBasePage: Page
{
    readonly Type _t;

    protected override void OnInit(EventArgs e)
    {
        _t = Business.GetPageType();
    }
}

Then alter all your pages to inherit from this instead of the normal Page class: 然后将所有页面改为继承,而不是普通的Page类:

public partial class FrontEnd: CustomBasePage

This means you only need to define your logic once and places a minimal overhead on the rest of the applications pages. 这意味着您只需要定义一次逻辑,并在其余的应用程序页面上放置最小的开销。 If any page need to override OnInit for another reason, it just needs to include a call to base.OnInit(); 如果任何页面由于其他原因需要覆盖OnInit ,它只需要包含对base.OnInit();的调用base.OnInit(); which isn't too onerous. 这不是太繁重。

You'll need to ensure that your Business.GetPageType(); 您需要确保您的Business.GetPageType(); return what you expect. 回报你的期望。 I'm not clear on exactly what it is doing and whether it will return the FrontEnd or CustomBasePage class, (nor which of those would be acceptable to your application logic). 我不清楚它到底在做什么,以及它是否会返回FrontEndCustomBasePage类,(或者你的应用程序逻辑可以接受哪些类)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM