【问题标题】:How to read assembly attributes如何读取程序集属性
【发布时间】:2008-10-09 14:23:34
【问题描述】:

在我的程序中,如何读取 AssemblyInfo.cs 中设置的属性:

[assembly: AssemblyTitle("My Product")]
[assembly: AssemblyDescription("...")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Radeldudel inc.")]
[assembly: AssemblyProduct("My Product")]
[assembly: AssemblyCopyright("Copyright @ me 2008")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

我想向我的程序的用户显示其中一些值,所以我想知道如何从主程序和我正在使用的组件程序集中加载它们。

【问题讨论】:

    标签: .net reflection assemblies attributes


    【解决方案1】:

    这相当容易。你必须使用反射。您需要一个 Assembly 实例,该实例代表具有您要读取的属性的程序集。一个简单的方法是这样做:

    typeof(MyTypeInAssembly).Assembly
    

    那么你可以这样做,例如:

    object[] attributes = assembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false);
    
    AssemblyProductAttribute attribute = null;
    if (attributes.Length > 0)
    {
       attribute = attributes[0] as AssemblyProductAttribute;
    }
    

    引用 attribute.Product 现在将为您提供您传递给 AssemblyInfo.cs 中属性的值。当然,如果您查找的属性可以多次出现,您可能会在 GetCustomAttributes 返回的数组中获得多个实例,但这对于您希望检索的程序集级属性通常不是问题。

    【讨论】:

    • 也可以使用Assembly.GetExecutingAssembly().GetCustomAttributes()来获取当前正在执行的程序集的属性。
    • 请注意,如果您正在读取未加载程序集的属性,则加载过程无法撤消,除非使用单独的 AppDomain 然后卸载。
    • GetExecutingAssembly 并不总是提供您想要的(例如,如果调试器启动了您的应用程序,它可以返回调试器)。
    • 不是:Assembly.GetAssembly(typeof(MyTypeInAssembly)) 吗? (可能改变了版本?)
    • @nashwan 不错。没有变化;我只是写了GetAssembly() 而不是Assembly
    【解决方案2】:

    我个人非常喜欢lance Larsen and his static AssemblyInfo class的实现。

    一个基本上将类粘贴到他的程序集中(我通常使用已经存在的 AssemblyInfo.cs 文件,因为它符合命名约定)

    要粘贴的代码是:

    internal static class AssemblyInfo
    {
        public static string Company { get { return GetExecutingAssemblyAttribute<AssemblyCompanyAttribute>(a => a.Company); } }
        public static string Product { get { return GetExecutingAssemblyAttribute<AssemblyProductAttribute>(a => a.Product); } }
        public static string Copyright { get { return GetExecutingAssemblyAttribute<AssemblyCopyrightAttribute>(a => a.Copyright); } }
        public static string Trademark { get { return GetExecutingAssemblyAttribute<AssemblyTrademarkAttribute>(a => a.Trademark); } }
        public static string Title { get { return GetExecutingAssemblyAttribute<AssemblyTitleAttribute>(a => a.Title); } }
        public static string Description { get { return GetExecutingAssemblyAttribute<AssemblyDescriptionAttribute>(a => a.Description); } }
        public static string Configuration { get { return GetExecutingAssemblyAttribute<AssemblyConfigurationAttribute>(a => a.Configuration); } }
        public static string FileVersion { get { return GetExecutingAssemblyAttribute<AssemblyFileVersionAttribute>(a => a.Version); } }
    
        public static Version Version { get { return Assembly.GetExecutingAssembly().GetName().Version; } }
        public static string VersionFull { get { return Version.ToString(); } }
        public static string VersionMajor { get { return Version.Major.ToString(); } }
        public static string VersionMinor { get { return Version.Minor.ToString(); } }
        public static string VersionBuild { get { return Version.Build.ToString(); } }
        public static string VersionRevision { get { return Version.Revision.ToString(); } }
    
        private static string GetExecutingAssemblyAttribute<T>(Func<T, string> value) where T : Attribute
        {
            T attribute = (T)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(T));
            return value.Invoke(attribute);
        }
    }
    

    你添加一个 using System;到文件的顶部,你就可以开始了。

    对于我的应用程序,我使用此类来设置/获取/使用我的本地用户设置:

    internal class ApplicationData
    {
    
        DirectoryInfo roamingDataFolder;
        DirectoryInfo localDataFolder;
        DirectoryInfo appDataFolder;
    
        public ApplicationData()
        {
            appDataFolder = new DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), AssemblyInfo.Product,"Data"));
            roamingDataFolder = new DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),AssemblyInfo.Product));
            localDataFolder   = new DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), AssemblyInfo.Product));
    
            if (!roamingDataFolder.Exists)            
                roamingDataFolder.Create();
    
            if (!localDataFolder.Exists)
                localDataFolder.Create();
            if (!appDataFolder.Exists)
                appDataFolder.Create();
    
        }
    
        /// <summary>
        /// Gets the roaming application folder location.
        /// </summary>
        /// <value>The roaming data directory.</value>
        public DirectoryInfo RoamingDataFolder => roamingDataFolder;
    
    
        /// <summary>
        /// Gets the local application folder location.
        /// </summary>
        /// <value>The local data directory.</value>
        public DirectoryInfo LocalDataFolder => localDataFolder;
    
        /// <summary>
        /// Gets the local data folder location.
        /// </summary>
        /// <value>The local data directory.</value>
        public DirectoryInfo AppDataFolder => appDataFolder;
    }
    

    看看 Larsens 网站 (MVP),他有很酷的东西可以从中汲取灵感。

    【讨论】:

      【解决方案3】:

      好的,我试图通过许多资源找到一种方法来提取 Assembly.LoadFrom(path) 的 .dll 属性。但不幸的是,我找不到任何好的资源。这个问题是在c# get assembly attributes 上搜索的最高结果(至少对我而言)所以我想分享我的工作。

      经过数小时的努力,我编写了以下简单的控制台程序来检索通用程序集属性。在这里,我提供了代码,因此任何人都可以将其用于进一步的参考工作。

      我为此使用CustomAttributes 属性。随意评论这种方法

      代码:

      using System;
      using System.Reflection;
      
      namespace MetaGetter
      {
          class Program
          {
              static void Main(string[] args)
              {
                  Assembly assembly = Assembly.LoadFrom("Path to assembly");
      
                  foreach (CustomAttributeData attributedata in assembly.CustomAttributes)
                  {
                      Console.WriteLine(" Name : {0}",attributedata.AttributeType.Name);
      
                      foreach (CustomAttributeTypedArgument argumentset in attributedata.ConstructorArguments)
                      {
                          Console.WriteLine("   >> Value : {0} \n" ,argumentset.Value);
                      }
                  }
      
                  Console.ReadKey();
              }
          }
      }
      

      样本输出:

      Name : AssemblyTitleAttribute
         >> Value : "My Product"
      

      【讨论】:

      【解决方案4】:

      我创建了这个使用 Linq 的扩展方法:

      public static T GetAssemblyAttribute<T>(this System.Reflection.Assembly ass) where T :  Attribute
      {
          object[] attributes = ass.GetCustomAttributes(typeof(T), false);
          if (attributes == null || attributes.Length == 0)
              return null;
          return attributes.OfType<T>().SingleOrDefault();
      }
      

      然后你可以方便地使用它:

      var attr = targetAssembly.GetAssemblyAttribute<AssemblyDescriptionAttribute>();
      if(attr != null)
           Console.WriteLine("{0} Assembly Description:{1}", Environment.NewLine, attr.Description);
      

      【讨论】:

      • 一个优秀的实用方法。对有兴趣获取程序集版本的人的快速提示。使用:assembly.GetAssemblyAttribute()(详情:stackoverflow.com/questions/1144525/…
      • 对于那些后来发现这个的人,这个扩展方法已经成为.NET since 4.5的一部分
      【解决方案5】:

      如果您知道要查找的属性是唯一的,那么使用 Attribute 类的这个经常被忽视的静态帮助方法会更容易:

      var attribute = Attribute.GetCustomAttribute(assembly, typeof(AssemblyTitleAttribute))
      

      这更容易,因为您不需要搞乱数组,或者担心那个讨厌的inherit 参数。您只需直接获取单个属性值,如果不存在,则为 null

      【讨论】:

        【解决方案6】:

        这是在一行代码中检索特定属性的好方法。不需要特殊课程。

        string company = ((AssemblyCompanyAttribute)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(AssemblyCompanyAttribute), false)).Company;
        

        【讨论】:

        • 纯代码答案经常被标记为“低质量帖子”!那么,也许你可以补充几句解释?
        • @Adrian:不言自明。如果我只需要一个属性,这就是要走的路。感谢您的反馈。
        【解决方案7】:

        我用这个:

        public static string Title
        {
            get
            {
                return GetCustomAttribute<AssemblyTitleAttribute>(a => a.Title);
            }
        }
        

        供参考:

        using System;
        using System.Reflection;
        using System.Runtime.CompilerServices;
        
        
        
        namespace Extensions
        {
        
        
            public static class AssemblyInfo
            {
        
        
                private static Assembly m_assembly;
        
                static AssemblyInfo()
                {
                    m_assembly = Assembly.GetEntryAssembly();
                }
        
        
                public static void Configure(Assembly ass)
                {
                    m_assembly = ass;
                }
        
        
                public static T GetCustomAttribute<T>() where T : Attribute
                {
                    object[] customAttributes = m_assembly.GetCustomAttributes(typeof(T), false);
                    if (customAttributes.Length != 0)
                    {
                        return (T)((object)customAttributes[0]);
                    }
                    return default(T);
                }
        
                public static string GetCustomAttribute<T>(Func<T, string> getProperty) where T : Attribute
                {
                    T customAttribute = GetCustomAttribute<T>();
                    if (customAttribute != null)
                    {
                        return getProperty(customAttribute);
                    }
                    return null;
                }
        
                public static int GetCustomAttribute<T>(Func<T, int> getProperty) where T : Attribute
                {
                    T customAttribute = GetCustomAttribute<T>();
                    if (customAttribute != null)
                    {
                        return getProperty(customAttribute);
                    }
                    return 0;
                }
        
        
        
                public static Version Version
                {
                    get
                    {
                        return m_assembly.GetName().Version;
                    }
                }
        
        
                public static string Title
                {
                    get
                    {
                        return GetCustomAttribute<AssemblyTitleAttribute>(
                            delegate(AssemblyTitleAttribute a)
                            {
                                return a.Title;
                            }
                        );
                    }
                }
        
                public static string Description
                {
                    get
                    {
                        return GetCustomAttribute<AssemblyDescriptionAttribute>(
                            delegate(AssemblyDescriptionAttribute a)
                            {
                                return a.Description;
                            }
                        );
                    }
                }
        
        
                public static string Product
                {
                    get
                    {
                        return GetCustomAttribute<AssemblyProductAttribute>(
                            delegate(AssemblyProductAttribute a)
                            {
                                return a.Product;
                            }
                        );
                    }
                }
        
        
                public static string Copyright
                {
                    get
                    {
                        return GetCustomAttribute<AssemblyCopyrightAttribute>(
                            delegate(AssemblyCopyrightAttribute a)
                            {
                                return a.Copyright;
                            }
                        );
                    }
                }
        
        
        
                public static string Company
                {
                    get
                    {
                        return GetCustomAttribute<AssemblyCompanyAttribute>(
                            delegate(AssemblyCompanyAttribute a)
                            {
                                return a.Company;
                            }
                        );
                    }
                }
        
        
                public static string InformationalVersion
                {
                    get
                    {
                        return GetCustomAttribute<AssemblyInformationalVersionAttribute>(
                            delegate(AssemblyInformationalVersionAttribute a)
                            {
                                return a.InformationalVersion;
                            }
                        );
                    }
                }
        
        
        
                public static int ProductId
                {
                    get
                    {
                        return GetCustomAttribute<AssemblyProductIdAttribute>(
                            delegate(AssemblyProductIdAttribute a)
                            {
                                return a.ProductId;
                            }
                        );
                    }
                }
        
        
                public static string Location
                {
                    get
                    {
                        return m_assembly.Location;
                    }
                }
        
            }
        
        }
        

        【讨论】:

        • public static int ProductId { get { return GetCustomAttribute( delegate(AssemblyProductIdAttribute a) { return a.ProductId; } );在这里,`AssemblyProductIdAttribute' 错误 -> 找不到类型或命名空间名称 'AssemblyProductIdAttribute'(您是否缺少 using 指令或程序集引用?)
        • Pritam:您缺少命名空间 System.Reflection(使用 System.Reflection;),或者您使用的是奇怪的框架版本/版本。 msdn.microsoft.com/en-us/library/…
        • using System.Reflection 包含在代码中,我可以轻松使用其他功能。他们都没有给出任何错误。另外,Framework也是正确的。
        • @Pritam:你在使用 .NET Core 吗?因为这应该是从 1.1 到 4.*,包括 Silverlight。是的,刚刚尝试过 - 该属性在 .NET Core 中不可用。
        • 另外,对于 .NET Core,它是: public static T GetCustomAttribute() where T : Attribute { IEnumerable customAttributes = m_assembly.GetCustomAttributes(); foreach(customAttributes 中的 thisAttribute 属性){ return (T)((object)thisAttribute); } 返回默认值(T); }
        【解决方案8】:

        好的,对于最初的问题,现在可能有点过时了,但无论如何我都会提出这个以供将来参考。

        如果您想从程序集内部执行此操作,请使用以下命令:

        using System.Runtime.InteropServices;
        using System.Reflection;
        
        object[] customAttributes = this.GetType().Assembly.GetCustomAttributes(false);
        

        然后您可以遍历所有自定义属性以找到您需要的属性,例如

        foreach (object attribute in customAttributes)
        {
          string assemblyGuid = string.Empty;    
        
          if (attribute.GetType() == typeof(GuidAttribute))
          {
            assemblyGuid = ((GuidAttribute) attribute).Value;
            break;
          }
        }
        

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-21
        • 2020-01-10
        • 2018-01-04
        • 2015-04-29
        • 2021-11-23
        • 1970-01-01
        • 1970-01-01
        • 2013-09-01
        相关资源
        最近更新 更多