We demonstrated two approaches to retrieve custom assembly attributes in early posts.
One is to call the Assembly.GetCustomAttributes() method and loop through all the returned attribute objects, check what attribute type each object is, and cast the instance to the right type to get the attribute value. The other is to call the GetCustomAttribute() method of the corresponding each attribute type such as the AssemblyInformationalVersionAttribute and access to the right property.
However, we have to cast an attribute instance to the right attribute type of concern one by one so as to read the wanted information out in both approaches. It is not convenient as we have to create a conditional branch for each available attribute type and likely some attributes may be missed out. Needless to say, more custom attribute types can be added over time, and some might be renamed though chance is very slight no one can guarantee.
Is there a way to parse out all the custom attribute information without doing any casting?
The first thought is to call the ToString() method against each attribute object but it will give us the type name instead of the attribute value that is expected, though the attribute value cannot be other than a string or a Boolean. Fortunately, another way is found out through some inspections on the attribute type and its properties.
It’s found that each attribute type has two properties, one of which is the TypeId and the other one is the value property such as Title, Company, or Configuration. So a concise and generic approach can be worked out through reflection.
private Dictionary<string, string> GetAssemblyInfo2(Assembly asm)
{
Object[] atts = asm.GetCustomAttributes(false);
Dictionary<string, string> asmValues = new Dictionary<string, string>();
foreach (Object obj in atts)
{
PropertyInfo[] piArr = obj.GetType().GetProperties();
foreach (PropertyInfo pi in piArr)
{
if (pi.Name != "TypeId")
{
string attValue = pi.GetValue(obj, null).ToString();
asmValues.Add(obj.GetType().Name, attValue);
break;
}
}
}
return asmValues;
}
Here is the code to exercise the help method:
Dictionary<string, string> asmValues = GetAssemblyInfo2(Assembly.GetEntryAssembly());
string str = string.Empty;
foreach (KeyValuePair<string, string> v in asmValues)
{
str += string.Format("{0}: {1}\n", v.Key, v.Value);
}
MessageBox.Show(str, "Assembly Information");
Here is the output:
All are good, aren’t they?
Another common task is to find out the value for a specific assembly attribute from the returned dictionary. The code is also simple and functional. We have worked out two signatures. One accepts an attribute name string and the other one attribute type:
private string GetAttributeValue(string name)
{
Dictionary<string, string> asmValues = GetAssemblyInfo2(Assembly.GetEntryAssembly());
if (asmValues.Keys.Contains(name))
return asmValues[name];
else
return "Not found!";
}
private string GetAttributeValue(Type t)
{
Dictionary<string, string> asmValues = GetAssemblyInfo2(Assembly.GetEntryAssembly());
if (asmValues.Keys.Contains(t.Name))
return asmValues[t.Name];
else
return "Not found!";
}
The test code looks like:
…
MessageBox.Show(GetAttributeValue("AssemblyConfigurationAttribute"));
MessageBox.Show(GetAttributeValue(typeof(AssemblyVersionAttribute)));
…
The second signature is strongly recommended since it will get rid of any typo issues.
AssemblyInfo Updater of RevitAddinWidget can help review popular assembly information of all available projects in a Visual Studio solution and update the information conveniently and flexibly in a single central place.
Recent Comments