【问题标题】:C# - Get calling method's Assembly?C# - 获取调用方法的程序集?
【发布时间】:2011-03-29 20:55:21
【问题描述】:

在 C# 中有没有办法获取 调用 方法的程序集? (不是当前方法。)

即我想要执行程序集,在调用堆栈中的上面一个。

【问题讨论】:

  • 已编辑标签; [assembly] 用于汇编语言问题。

标签: c# .net reflection


【解决方案1】:

试试这个

Assembly.GetCallingAssembly();

【讨论】:

  • 我要的是调用方法的汇编,不是当前方法。
  • err - 这将为您提供调用方法的程序集,而不是当前方法。 GetExecutingAssembly 为您提供当前方法的程序集。 Stecya 是正确的。
  • 内联可以使这个不可靠 - 请参阅msdn.microsoft.com/en-us/library/…中的备注部分
  • 那就不要内联了:) [MethodImplAttribute(MethodImplOptions.NoInlining)]
  • 也要注意尾调用。 tail call 将是例如 return Assembly.GetCallingAssembly(); - 它也可能被编译器优化,因此返回意外结果。属性不能阻止尾调用优化,只能通过避免使用 return 语句“内联”调用函数。
【解决方案2】:

这个怎么样:

StackTrace stackTrace = new StackTrace();           // get call stack

var assembly = stackTrace.GetFrame(0).GetMethod().DeclaringType.Assembly;

在http://www.csharp-examples.net/reflection-callstack/的帮助下

【讨论】:

  • 这会在 JIT 内联方法时中断。
  • JIT 内联方法什么时候使用?
  • 是JIT优化,所以根据内部实现来决定。使用属性可以防止内联:stackoverflow.com/questions/5169219/…
【解决方案3】:

这是我用的:

        var stackFrames = new StackTrace().GetFrames();
        if(stackFrames==null) return null;
        var executingAssembly = Assembly.GetExecutingAssembly();
        foreach (var frame in stackFrames)
        {
            var assembly = frame.GetMethod().DeclaringType.Assembly;
            if (assembly != executingAssembly)
            {
                return assembly;
            }
        }
        return null;

【讨论】:

    【解决方案4】:

    不,不可能可靠地了解谁在给您打电话。毫无疑问,有些人会建议堆栈遍历,但由于 JIT 内联,这是不可靠的。没有办法可靠地获取调用您的方法的方法/程序集。

    【讨论】:

    • 如 Stecya 之前向我指出的,Assembly.GetCallingAssembly() 怎么样?
    【解决方案5】:

    编写此代码是为了获取调用程序集的 AssemblyInfo.cs 属性——因此使用“GetAssembly(int stackTraceLevel)”方法来完成所需的操作...

    所有这些也都在我的博客http://lancelarsen.com/reading-values-from-assemblyinfo-cs/

    享受

    /// <summary>
    /// Gets the values from the AssemblyInfo.cs file for the previous assembly
    /// </summary>
    /// <example>
    /// AssemblyInfoCalling assembly = new AssemblyInfoCalling();
    /// string company1 = assembly.Company;
    /// string product1 = assembly.Product;
    /// string copyright1 = assembly.Copyright;
    /// string trademark1 = assembly.Trademark;
    /// string title1 = assembly.Title;
    /// string description1 = assembly.Description;
    /// string configuration1 = assembly.Configuration;
    /// string fileversion1 = assembly.FileVersion;
    /// Version version1 = assembly.Version;
    /// string versionFull1 = assembly.VersionFull;
    /// string versionMajor1 = assembly.VersionMajor;
    /// string versionMinor1 = assembly.VersionMinor;
    /// string versionBuild1 = assembly.VersionBuild;
    /// string versionRevision1 = assembly.VersionRevision;
    /// </example>
    public class AssemblyInfoCalling
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="AssemblyInfoCalling"/> class.
        /// </summary>
        /// <param name="traceLevel">The trace level needed to get correct assembly 
        /// - will need to adjust based on where you put these classes in your project(s).</param>
        public AssemblyInfoCalling(int traceLevel = 4)
        {
            //----------------------------------------------------------------------
            // Default to "3" as the number of levels back in the stack trace to get the 
            //  correct assembly for "calling" assembly
            //----------------------------------------------------------------------
            StackTraceLevel = traceLevel;
        }
    
        //----------------------------------------------------------------------
        // Standard assembly attributes
        //----------------------------------------------------------------------
        public string Company { get { return GetCallingAssemblyAttribute<AssemblyCompanyAttribute>(a => a.Company); } }
        public string Product { get { return GetCallingAssemblyAttribute<AssemblyProductAttribute>(a => a.Product); } }
        public string Copyright { get { return GetCallingAssemblyAttribute<AssemblyCopyrightAttribute>(a => a.Copyright); } }
        public string Trademark { get { return GetCallingAssemblyAttribute<AssemblyTrademarkAttribute>(a => a.Trademark); } }
        public string Title { get { return GetCallingAssemblyAttribute<AssemblyTitleAttribute>(a => a.Title); } }
        public string Description { get { return GetCallingAssemblyAttribute<AssemblyDescriptionAttribute>(a => a.Description); } }
        public string Configuration { get { return GetCallingAssemblyAttribute<AssemblyDescriptionAttribute>(a => a.Description); } }
        public string FileVersion { get { return GetCallingAssemblyAttribute<AssemblyFileVersionAttribute>(a => a.Version); } }
    
        //----------------------------------------------------------------------
        // Version attributes
        //----------------------------------------------------------------------
        public static Version Version
        {
            get
            {
                //----------------------------------------------------------------------
                // Get the assembly, return empty if null
                //----------------------------------------------------------------------
                Assembly assembly = GetAssembly(StackTraceLevel);
                return assembly == null ? new Version() : assembly.GetName().Version;
            }
        }
        public string VersionFull { get { return Version.ToString(); } }
        public string VersionMajor { get { return Version.Major.ToString(); } }
        public string VersionMinor { get { return Version.Minor.ToString(); } }
        public string VersionBuild { get { return Version.Build.ToString(); } }
        public string VersionRevision { get { return Version.Revision.ToString(); } }
    
        //----------------------------------------------------------------------
        // Set how deep in the stack trace we're looking - allows for customized changes
        //----------------------------------------------------------------------
        public static int StackTraceLevel { get; set; }
    
        //----------------------------------------------------------------------
        // Custom Attributes
        //----------------------------------------------------------------------
        public string Location 
        { 
            get
            {
                try
                {
                    return GetCallingAssemblyAttribute<AssemblyLocationAttribute>(a => a.Value);
                }
                catch (NullReferenceException)
                {
                    return string.Empty;
                }
    
            } 
        }
    
        /// <summary>
        /// Gets the calling assembly attribute.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value">The value.</param>
        /// <example>return GetCallingAssemblyAttribute&lt;AssemblyCompanyAttribute&gt;(a => a.Company);</example>
        /// <returns></returns>
        private string GetCallingAssemblyAttribute<T>(Func<T, string> value) where T : Attribute
        {
            //----------------------------------------------------------------------
            // Get the assembly, return empty if null
            //----------------------------------------------------------------------
            Assembly assembly = GetAssembly(StackTraceLevel);
            if (assembly == null) return string.Empty;
    
            //----------------------------------------------------------------------
            // Get the attribute value
            //----------------------------------------------------------------------
            T attribute = (T) Attribute.GetCustomAttribute(assembly, typeof (T));
            return value.Invoke(attribute);
        }
    
        /// <summary>
        /// Go through the stack and gets the assembly
        /// </summary>
        /// <param name="stackTraceLevel">The stack trace level.</param>
        /// <returns></returns>
        private static Assembly GetAssembly(int stackTraceLevel)
        {
            //----------------------------------------------------------------------
            // Get the stack frame, returning null if none
            //----------------------------------------------------------------------
            StackTrace stackTrace = new StackTrace();
            StackFrame[] stackFrames = stackTrace.GetFrames();
            if (stackFrames == null) return null;
    
            //----------------------------------------------------------------------
            // Get the declaring type from the associated stack frame, returning null if nonw
            //----------------------------------------------------------------------
            var declaringType = stackFrames[stackTraceLevel].GetMethod().DeclaringType;
            if (declaringType == null) return null;
    
            //----------------------------------------------------------------------
            // Return the assembly
            //----------------------------------------------------------------------
            var assembly = declaringType.Assembly;
            return assembly;
        }
    }
    

    【讨论】:

      【解决方案6】:

      偶然发现这个寻找类似的东西。就我而言,它是Assembly.GetEntryAssembly()。

      用例

      程序 A 运行 CodeDomProvider.CompileAssemblyFromSource 以嵌入资源并编译程序 B。程序 B 中的 DLL 然后读取资源,但不知道程序集(上面解决了这个问题)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-04-29
        • 1970-01-01
        • 1970-01-01
        • 2012-02-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多