Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Getting Assembly Information Using Reflection

DZone's Guide to

Getting Assembly Information Using Reflection

· Agile Zone
Free Resource

Speed up delivery cycles and improve software quality with TestComplete. Discover the most robust automated testing tool for end-to-end desktop, mobile, and web testing. Try TestComplete Free.

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!

Release quality software faster with TestComplete. Discover how to decrease testing times and expand test coverage with the most robust automated UI testing tool. Try free for 30 days.

Topics:

Published at DZone with permission of Michael Ceranski, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}