c# - getfield - Web應用程序的GetEntryAssembly




methodinfo c# (4)

Assembly.GetEntryAssembly()不適用於Web應用程序。

但是......我真的需要這樣的東西。 我使用一些在Web和非Web應用程序中使用的深層嵌套代碼。

我目前的解決方案是瀏覽StackTrace以找到第一個被調用的程序集。

/// <summary>
/// Version of 'GetEntryAssembly' that works with web applications
/// </summary>
/// <returns>The entry assembly, or the first called assembly in a web application</returns>
public static Assembly GetEntyAssembly()
{
    // get the entry assembly
    var result = Assembly.GetEntryAssembly();

    // if none (ex: web application)
    if (result == null)
    {
        // current method
        MethodBase methodCurrent = null;
        // number of frames to skip
        int framestoSkip = 1;


        // loop until we cannot got further in the stacktrace
        do
        {
            // get the stack frame, skipping the given number of frames
            StackFrame stackFrame = new StackFrame(framestoSkip);
            // get the method
            methodCurrent = stackFrame.GetMethod();
            // if found
            if ((methodCurrent != null)
                // and if that method is not excluded from the stack trace
                && (methodCurrent.GetAttribute<ExcludeFromStackTraceAttribute>(false) == null))
            {
                // get its type
                var typeCurrent = methodCurrent.DeclaringType;
                // if valid
                if (typeCurrent != typeof (RuntimeMethodHandle))
                {
                    // get its assembly
                    var assembly = typeCurrent.Assembly;

                    // if valid
                    if (!assembly.GlobalAssemblyCache
                        && !assembly.IsDynamic
                        && (assembly.GetAttribute<System.CodeDom.Compiler.GeneratedCodeAttribute>() == null))
                    {
                        // then we found a valid assembly, get it as a candidate
                        result = assembly;
                    }
                }
            }

            // increase number of frames to skip
            framestoSkip++;
        } // while we have a working method
        while (methodCurrent != null);
    }
    return result;
}

為了確保組裝符合我們的要求,我們有三個條件:

  • 該程序集不在GAC中
  • 組裝沒有動態
  • 不生成程序集(避免臨時的asp.net文件

我遇到的最後一個問題是何時在單獨的程序集中定義基頁。 (我使用ASP.Net MVC,但ASP.Net也是如此)。 在這種特殊情況下,它是返回的單獨程序集,而不是包含頁面的程序集。

我現在正在尋找的是:

1)我的裝配驗證條件是否足夠? (我可能已經忘記了案件)

2)從ASP.Net臨時文件夾中的給定代碼生成的程序集中,是否有一種方法可以獲取有關包含該頁面/視圖的項目的信息? (我想不是,但誰知道...)

https://code.i-harness.com


作為我自己的問題的答案(這裡的一些人對接受率非常敏感)=>我找不到比問題中給出的代碼更好的方法。

這意味著te解決方案並不完美,但只要您的基頁在前端程序集中定義,它就可以工作。


問題中提出的算法確實對我有用,而使用System.Web.HttpContext.Current.ApplicationInstance的方法卻沒有。 我認為我的問題是我需要解決方案的舊式ASP.Net應用程序缺少global.asax處理程序。

這個較短的解決方案也適用於我,我認為通常會在前端程序集中定義頁面處理程序的條件下工作:

    private static Assembly GetMyEntryAssembly()
    {
      if ((System.Web.HttpContext.Current == null) || (System.Web.HttpContext.Current.Handler == null))
        return Assembly.GetEntryAssembly(); // Not a web application
      return System.Web.HttpContext.Current.Handler.GetType().BaseType.Assembly;
    }

我的應用程序是ASP.Net 4.x Web表單應用程序。 對於此應用程序類型,HttpContext.Current.Handler是包含當前請求處理程序的入口點的代碼模塊。 Handler.GetType()。Assembly是一個臨時的ASP.Net程序集,但Handler.GetType()。BaseType.Assembly是我的應用程序的真正“入口程序集”。 我很好奇,如果它適用於各種其他ASP.Net應用程序類型。


我能夠使Web應用程序(至少在.NET 4.5.1中)一致地工作的唯一方法是在Web應用程序項目本身中執行Assembly.GetExecutingAssembly()。

如果您嘗試使用靜態方法創建實用程序項目並在那裡進行調用,則將從該程序集中獲取程序集信息 - 對於GetExecutingAssembly()和GetCallingAssembly()。

GetExecutingAssembly()是一個返回Assembly類型實例的靜態方法。 該方法在Assembly類本身的實例上不存在。

所以,我所做的是創建了一個在構造函數中接受Assembly類型的類,並創建了一個傳遞Assembly.GetExecutingAssembly()結果的類的實例。

    public class WebAssemblyInfo
    {
        Assembly assy;

        public WebAssemblyInfo(Assembly assy)
        {
            this.assy = assy;
        }

        public string Description { get { return GetWebAssemblyAttribute<AssemblyDescriptionAttribute>(a => a.Description); } }


         // I'm using someone else's idea below, but I can't remember who it was
        private string GetWebAssemblyAttribute<T>(Func<T, string> value) where T : Attribute
        {
            T attribute = null;

            attribute = (T)Attribute.GetCustomAttribute(this.assy, typeof(T));

            if (attribute != null)
                return value.Invoke(attribute);
            else
                return string.Empty;
        }
    }
}

並使用它

string Description = new WebAssemblyInfo(Assembly.GetExecutingAssembly()).Description;

這似乎是一種可靠,簡單的方法來獲取Web應用程序的“入口”或主要程序集。

如果你把控制器放在一個單獨的項目中,你可能會發現ApplicationInstance的基類與包含Views的MVC項目不在同一個程序集中 - 但是,這個設置似乎很少見(我提到它因為我試過這個設置在一個點,一段時間後,一些博客支持這個想法)。

    static private Assembly GetWebEntryAssembly()
    {
        if (System.Web.HttpContext.Current == null ||
            System.Web.HttpContext.Current.ApplicationInstance == null) 
        {
            return null;
        }

        var type = System.Web.HttpContext.Current.ApplicationInstance.GetType();
        while (type != null && type.Namespace == "ASP") {
            type = type.BaseType;
        }

        return type == null ? null : type.Assembly;
    }




stackframe