Cómo leer atributos de ensamblado


En mi programa, cómo puedo leer las propiedades establecidas en 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("")]

Me gustaría mostrar algunos de estos valores al usuario de mi programa, así que me gustaría saber cómo cargarlos desde el programa principal y desde los ensamblados de komponent que estoy usando.

Author: starblue, 2008-10-09

6 answers

Esto es razonablemente fácil. Tienes que usar la reflexión. Necesita una instancia de Ensamblado que represente el ensamblado con los atributos que desea leer. Una manera fácil de conseguir esto es hacer:

typeof(MyTypeInAssembly).Assembly

Entonces puedes hacer esto, por ejemplo:

object[] attributes = assembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false);

AssemblyProductAttribute attribute = null;
if (attributes.Length > 0)
{
   attribute = attributes[0] as AssemblyProductAttribute;
}

Hacer referencia a attribute.Product ahora le dará el valor que pasó al atributo en su AssemblyInfo.cs. Por supuesto, si el atributo que busca puede ocurrir más de una vez, puede obtener varias instancias en la matriz devueltas por GetCustomAttributes, pero esto no suele ser un problema para los atributos de nivel de ensamblado como los que espera recuperar.

 52
Author: Jeff Yates,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-23 16:16:15

He creado este método de extensión que usa 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();
}

Y luego puedes usarlo convenientemente así:

var attr = targetAssembly.GetAssemblyAttribute<AssemblyDescriptionAttribute>();
if(attr != null)
     Console.WriteLine("{0} Assembly Description:{1}", Environment.NewLine, attr.Description);
 13
Author: dmihailescu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-19 16:39:46

Ok, tal vez un poco anticuado ahora para la pregunta original, pero presentaré esto para referencia futura de todos modos.

Si desea hacerlo desde el propio ensamblado, utilice lo siguiente:

using System.Runtime.InteropServices;
using System.Reflection;

object[] customAttributes = this.GetType().Assembly.GetCustomAttributes(false);

Luego puede iterar a través de todos los atributos personalizados para encontrar el uno(s) que necesita, por ejemplo,

foreach (object attribute in customAttributes)
{
  string assemblyGuid = string.Empty;    

  if (attribute.GetType() == typeof(GuidAttribute))
  {
    assemblyGuid = ((GuidAttribute) attribute).Value;
    break;
  }
}
 10
Author: ccellar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-24 10:03:48

Está bien, estoy tratando de ir a través de muchos recursos para encontrar un método para extraer .atributos dll para un Assembly.LoadFrom(path) . Pero desafortunadamente no pude encontrar ningún buen recurso. Y esta pregunta fue el resultado más alto para buscar en c# get assembly attributes (al menos para mí), así que pensé en compartir mi trabajo.

Escribí el siguiente programa de consola simple para recuperar los atributos de la asamblea general después de muchas horas de lucha. Aquí he proporcionado el código para que cualquiera pueda usarlo para trabajos de referencia adicionales.

Uso CustomAttributes propiedad para esto. No dude en comentar sobre este enfoque

Código:

using System;
using System.Reflection;

namespace MetaGetter
{
    class Program
    {
        static void Main(string[] args)
        {
            Assembly asembly = Assembly.LoadFrom("Path to assembly");

            foreach (CustomAttributeData atributedata in asembly.CustomAttributes)
            {
                Console.WriteLine(" Name : {0}",atributedata.AttributeType.Name);

                foreach (CustomAttributeTypedArgument argumentset in atributedata.ConstructorArguments)
                {
                    Console.WriteLine("   >> Value : {0} \n" ,argumentset.Value);
                }
            }

            Console.ReadKey();
        }
    }
}

Salida de muestra:

Name : AssemblyTitleAttribute
   >> Value : "My Product"
 4
Author: Kavindu Dodanduwa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-11 06:16:37

Yo uso esto:

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

Para referencia:

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;
            }
        }

    }

}
 1
Author: Stefan Steiger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-27 12:57:23

Personalmente me gusta mucho la implementación de lance Larsen y su clase estática AssemblyInfo .

Básicamente se pega la clase en su ensamblado (normalmente uso el AssemblyInfo ya existente.archivo cs, ya que se ajusta a la convención de nomenclatura)

El código a pegar es:

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<AssemblyDescriptionAttribute>(a => a.Description); } }
    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);
    }
}

Agregas un using System; a la parte superior del archivo y ya estás listo.

Para mis aplicaciones utilizo esta clase para establecer/get / work con la configuración de mis usuarios locales usando:

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;
}

Echa un vistazo al sitio web de Larsens (MVP), tiene cosas geniales de las que inspirarse.

 0
Author: Computer Aided Trading Systems,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-07 10:54:44