Sunday, November 11, 2007

AssemblyInfo and Related Utility Classes

I worked on one project where I need to get an assembly's information defined in the project's AssemblyInfo.cs. There are many ways to get these information. One way is by calling Assemlby class' method GetCustomAttributes() like this:

Assembly _assembly = Assembly.GetExecutingAssembly();
objects[] _assemblyAttributes = _assembly.GetCustomAttributes(true);

I tried to print out the array of retrieved attributes. There are 15 items. I thought the order of these attributes are pre-defined. Then I wrote a class to get some of assembly information out by the index.

However, I run into a problem. When I changed some attributes, for example AssemblyCulture(), my class does not work any more. I finally found out that the order of attributes in the object array are changed! Before I realized this, I tried other ways to get AssebmlyIno. Here is another class by using FileVerionInfo class:
using System;
using System.Reflection;
using System.Diagnostics;
using System.Globalization;
//...
class AssemblyInfo1
{
private Assembly _assembly;
private FileVersionInfo _fileInfo;

public AssemblyInfo1()
{
_assembly = Assembly.GetExecutingAssembly();
_fileInfo = FileVersionInfo.GetVersionInfo(_assembly.Location);

}

public string Title
{
get
{
return _fileInfo.Comments;
}
}

public string Description
{
get
{
return _fileInfo.Comments;
}
}

public string Company
{
get
{
return _fileInfo.CompanyName;
}
}

public string Product
{
get
{
return _fileInfo.ProductName;
}
}

public string CopyRight
{
get
{
return _fileInfo.LegalCopyright;
}
}

public string Trademark
{
get
{
return _fileInfo.LegalTrademarks;
}
}

public string FileVersion
{
get
{
return _fileInfo.FileVersion;
}
}

public string InformationVersion
{
get
{
return _fileInfo.ProductVersion;
}
}

public Version Version
{
get
{
return _assembly.GetName().Version;
}
}

public CultureInfo Culture
{
get
{
return _assembly.GetName().CultureInfo;
}
}
}

The only problem is that I could not find a way to get AssemblyConfiguration() information. After I realized the order change in the object array retrieved from GetCustomAttributes(), I changed the class with string comparing to get assembly's information. My second class can get AssemblyConfiguration() information.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Globalization;
using System.Diagnostics;
// ...
public class AssemblyInfo2
{
private const string TITLE = "System.Reflection.AssemblyTitleAttribute";
private const string DESCRIPTION = "System.Reflection.AssemblyDescriptionAttribute";
private const string CONFIGURATION = "System.Reflection.AssemblyConfigurationAttribute";
private const string COMPANY = "System.Reflection.AssemblyCompanyAttribute";
private const string PRODUCT = "System.Reflection.AssemblyProductAttribute";
private const string COPYRIGHT = "System.Reflection.AssemblyCopyrightAttribute";
private const string TRADEMARK = "System.Reflection.AssemblyTrademarkAttribute";
private const string FILE_VERSION = "System.Reflection.AssemblyFileVersionAttribute";
private const string INFORMATION_VERSION = "System.Reflection.AssemblyInformationalVersionAttribute";

private Assembly _assembly;
private object[] _assemblyAttributes;

public AssemblyInfo2()
{
_assembly = Assembly.GetExecutingAssembly();
_assemblyAttributes = _assembly.GetCustomAttributes(true);
}

private T GetAttribute<T>(string typeString)
where T : class
{
List<object> objects = new List<object>(_assemblyAttributes);
object assemblyObj = objects.Find(
delegate(object item)
{
bool found = false;
if (item != null)
{
found = item.ToString().Equals(typeString);
}
return found;
});

return assemblyObj as T;
}

public AssemblyTitleAttribute Title
{
get
{
return GetAttribute<AssemblyTitleAttribute>(TITLE);
}
}

public AssemblyDescriptionAttribute Description
{
get
{
return GetAttribute<AssemblyDescriptionAttribute>(DESCRIPTION);
}
}

public AssemblyConfigurationAttribute Configuration
{
get
{
return GetAttribute<AssemblyConfigurationAttribute>(CONFIGURATION);
}
}

public AssemblyCompanyAttribute Company
{
get
{
return GetAttribute<AssemblyCompanyAttribute>(COMPANY);
}
}

public AssemblyProductAttribute Product
{
get
{
return GetAttribute<AssemblyProductAttribute>(PRODUCT);
}
}

public AssemblyCopyrightAttribute CopyRight
{
get
{
return GetAttribute<AssemblyCopyrightAttribute>(COPYRIGHT);
}
}

public AssemblyTrademarkAttribute Trademark
{
get
{
return GetAttribute<AssemblyTrademarkAttribute>(TRADEMARK);
}
}

public AssemblyFileVersionAttribute FileVersion
{
get
{
return GetAttribute<AssemblyFileVersionAttribute>(FILE_VERSION);
}
}

public AssemblyInformationalVersionAttribute InformationVersion
{
get
{
return GetAttribute<AssemblyInformationalVersionAttribute>(INFORMATION_VERSION);
}
}

public Version Version
{
get
{
return _assembly.GetName().Version;
}
}

public CultureInfo Culture
{
get
{
return _assembly.GetName().CultureInfo;
}
}
}

By the way, the Culture property is based on AssemblyCulture("") setting in AssebmlyInfo.cs. You just cannot set this information other than empty string "". I tried to change it to "en" or "en-US". The project just cannot be compiled. Actually, this is the property I tried to change and I tried to change project's property from "assembly information..." in Application tab, and then the order of attributes retrieved from GetCustomeAttributes() is changed. It's very interesting issue. I am not sure how the assembly attribute information are populated in the assembly.

0 comments: