Wednesday, May 14, 2008

Accessing Attributes in AssemblyInfo.cs

Copyright © 2008, Steven E. Houchin
For a new C# .NET application, an AssemblyInfo.cs file is automatically created. It contains empty attributes that can be used to describe the assembly. These attributes are queried by Windows when the Properties of an executable are examined from Windows Explorer. They are also useful within the application itself to set the string in the title bar and for populating an About dialog. For example, I set the following values for one of my applications (with names changed to protect confidentiality):

[assembly: AssemblyTitle("My Application")]
[assembly: AssemblyCompany("Forest Park Lab")]
[assembly: AssemblyProduct("My Product")]
[assembly: AssemblyCopyright("Copyright © 2004-2008, Forest Park Lab.")]
[assembly: AssemblyTrademark("My Product ™ is a trademark of Forest Park Lab.")]

Setting these values doesn't make them automatically available to your application code. In order to access them, I have a piece of boilerplate code I include in the AssemblyInfo.cs file to make these attributes readily accessible. I define an "AssemblyInfo class" as follows:

using System.Reflection;
using System.Runtime.CompilerServices;

public class AssemblyInfo
{
   private AssemblyTitleAttribute  _title = null;
   private AssemblyCopyrightAttribute _copyright = null;
   private AssemblyProductAttribute _product = null;
   private string    _version;

   public AssemblyInfo()
   {
      System.Reflection.Assembly assembly =
      System.Reflection.Assembly.GetExecutingAssembly();
      // get the version string
      _version = assembly.GetName().Version.ToString();

      // get other desired attributes
      object[] attributes = assembly.GetCustomAttributes(false);
      for (int i = 0; i < attributes.Length; i ++)
      {
         if (_title == null)
         {
            _title = attributes[i]
               as AssemblyTitleAttribute;
            if (_title != null)
               continue;
         }
         if (_copyright == null)
         {
            _copyright = attributes[i]
               as AssemblyCopyrightAttribute;
            if (_copyright != null)
               continue;
         }
         if (_product == null)
         {
            _product = attributes[i]
               as AssemblyProductAttribute;
            if (_product != null)
               continue;
         }
      }
   }
   public string Title  { get { return _title.Title; } }
   public string Product  { get { return _product.Product; } }
   public string Copyright  { get { return _copyright.Copyright; } }
   public string Version  { get { return _version; } }
}

The way this code works is that it fetches all of the customizable attributes from the assembly (GetCustomAttributes()) into an array of objects. It then loops through each object and attempts to cast it (using the C# "as" operator) to one of the desired attribute types. If the cast fails, the result is null. Otherwise, the object is remembered as a property within the AssemblyInfo class for later access by the application.
To make use of these attributes in the application, simply create an instance of the AssemblyInfo class and access the properties, as follows:

AssemblyInfo appInfo = new AssemblyInfo();
// set the title in title bar
this.Text = appInfo.Title;
// set the product name
this.lblProduct.Text = appInfo.Product;