Как читать атрибуты сборки
В моей программе, как я могу прочитать свойства, установленные в 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("")]
Я хотел бы отобразить некоторые из этих значений для пользователя моей программы, поэтому я хотел бы знать, как их загрузить из основной программы и из составных компонентов, которые я использую.
Ответы
Ответ 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, но это обычно не проблема для атрибутов уровня сборки, таких как те, которые вы хотите получить.
Ответ 2
Я создал этот метод расширения, который использует 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);
Ответ 3
Хорошо, возможно, немного устарело сейчас для исходного вопроса, но я все равно покажу это для будущей справки.
Если вы хотите сделать это изнутри самой сборки, используйте следующее:
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;
}
}
Ответ 4
Хорошо, я пытаюсь пройти через множество ресурсов, чтобы найти способ извлечения атрибутов .dll для Assembly.LoadFrom(path)
. Но, к сожалению, я не смог найти хороший ресурс. И этот вопрос был самым большим результатом для поиска на c# get assembly attributes
(по крайней мере для меня). Поэтому я подумал о том, чтобы поделиться своей работой.
Я написал следующую простую консольную программу для получения общих атрибутов сборки после многих часов борьбы. Здесь я предоставил код, чтобы каждый мог использовать его для дальнейшей справочной работы.
Я использую для этого свойство CustomAttributes
. Не стесняйтесь прокомментировать этот подход
Код:
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();
}
}
}
Пример вывода:
Name : AssemblyTitleAttribute
>> Value : "My Product"
Ответ 5
Я использую это:
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;
}
}
}
}
Ответ 6
Мне лично очень нравится реализация Ланса Ларсена и его статического класса AssemblyInfo.
Один в основном вставляет класс в свою сборку (я обычно использую уже существующий файл 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<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);
}
}
Вы добавляете систему использования; в начало файла, и все готово.
Для своих приложений я использую этот класс для установки/получения/работы с настройками локальных пользователей, используя:
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;
}
Взгляните на веб-сайт Ларсена (MVP), у него есть классные вещи для вдохновения.
Ответ 7
Если вы знаете, что искомый атрибут уникален, гораздо проще использовать этот часто пропускаемый статический вспомогательный метод класса Attribute
:
var attribute = Attribute.GetCustomAttribute(assembly, typeof(AssemblyTitleAttribute))
Это проще, потому что вам не нужно возиться с массивами или беспокоиться об этом раздражающем параметре inherit
. Вы просто получаете одно значение атрибута напрямую или null
если его не существует.
Ответ 8
Это отличный способ получить определенные атрибуты в одной строке кода. Специальный класс не требуется.
string company = ((AssemblyCompanyAttribute)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(AssemblyCompanyAttribute), false)).Company;