.NET Zone is brought to you in partnership with:

Michael Ceranski is a .NET developer from Buffalo NY. He has been writing code for over 10 years starting with Borland Delphi and later migrating to the .NET stack. Michael enjoys blogging about .NET, MVC and jQuery. When Michael is not consulting he spends his time working on WeBlog, a next generation blogging platform written in ASP.NET MVC 2. Michael is a DZone MVB and is not an employee of DZone and has posted 34 posts at DZone. You can read more from them at their website. View Full User Profile

Getting Assembly Information Using Reflection

01.04.2012
| 2883 views |
  • submit to reddit

I recently took over a WPF application that needed a little bit of refactoring. One of the places that had a lot of repeated code was the about screen. By using reflection a bunch of properties were being created to display things like the assembly title, version, description and etcetera. The original code looked like this:

public string AssemblyDescription
{
    get
    {
        object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
        if (attributes.Length == 0)
        {
            return "";
        }
        return ((AssemblyDescriptionAttribute)attributes[0]).Description;
    }
}

public string AssemblyProduct
{
    get
    {
        object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
        if (attributes.Length == 0)
        {
            return "";
        }
        return ((AssemblyProductAttribute)attributes[0]).Product;
    }
}

You may have noticed that this code does not follow the DRY principle. In case you arent familiar with the term, DRY stands for Don't repeat yourself. In otherwords, if you repeat the same code multiple times then you should try to refactor it into a more generic method.

After analyzing the code you may notice that both of the property getters do the same thing. First, it gets a handle to the current assembly. Next, the GetCustomAttributes method is called to get an object array which contains all the attribute values for a given type. Finally, a little bit of conditional logic is used to emit a value. Using the power of generics and some reflection we can easily build an extension method that will eliminate the redundant code.

Warning: If you are not familiar with generics, reflection and lambda statements then the following code may cause your brain to explode

public static TAttribute[] GetAttributes<TAttribute>(this Assembly assembly) where TAttribute : Attribute {
    return assembly.GetCustomAttributes(typeof(TAttribute), false) as TAttribute[];
}

public static object GetFirstAttributeValue<TAttribute>(
    this Assembly assembly,
    Expression<Func<TAttribute, object>> propertyLambda) where TAttribute : Attribute {
    Type type = typeof(TAttribute);

    var attributeValues = assembly.GetAttributes<TAttribute>();
    if (attributeValues.Length == 0)
        throw new ArgumentException("No values found");

    var member = propertyLambda.Body as MemberExpression;
    if (member == null)
        throw new ArgumentException(string.Format("Expression '{0}' refers to a method, not a property.", propertyLambda));

    var propInfo = member.Member as PropertyInfo;
    if (propInfo == null)
        throw new ArgumentException(string.Format("Expression '{0}' refers to a field, not a property.", propertyLambda));

    if (type != propInfo.ReflectedType && !type.IsSubclassOf(propInfo.ReflectedType))
        throw new ArgumentException(string.Format("Expresion '{0}' refers to a property that is not from type {1}.", propertyLambda, type));

    var firstValue = attributeValues[0];
    return propInfo.GetValue(firstValue, null);
}

The code above basically takes the lambda statement, makes sure its a property expression and then uses reflection to get the value of the object. By the way, I do not take credit for writing the reflection code, most of it was borrowed from this stackoverflow post. In any case, with the help of the extension method above we can now simplify our code as:

private Assembly Assembly { get; set; }

public AboutViewModel()
{
    Assembly = Assembly.GetExecutingAssembly();
}

public string AssemblyDescription {
    get {
        return Assembly.GetFirstAttributeValue<AssemblyDescriptionAttribute>(x => x.Description).ToString();
    }
}

public string AssemblyProduct {
    get {
        return Assembly.GetFirstAttributeValue<AssemblyProductAttribute>(x => x.Product).ToString();
    }
}

As you can see, the code is much cleaner. Also take notice that I cached the call to Assembly.GetExecutingAssembly() in a private variable. This helps with performance and also cleans up the code a little.

Happy Coding!

References
Published at DZone with permission of Michael Ceranski, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)