Your First Attribute
But this article is about writing your own metadata and using it. Let's start with a common example: an assembly attribute that contains the name of the team that is responsible for the code (see ObjectLibrary for the full source files):
using System.Reflection; public class AssemblyTeamAttribute :
Attribute { }
First, we need to create a class that derives from the System.Reflection.Attribute class. Unlike the Serializable and NonSerialized attributes we mentioned above, we actually want to store some additional information to be stored in the metadata, so we add a constructor that takes a string containing the name of the team that is responsible for this assembly and a field to store it in (see ObjectLibrary for the full source files):
public AssemblyTeamAttribute(string teamName) { _teamName = teamName; } We also need to add a public property to retrieve the name of the team so that we
could have tools that can read the attribute: public string TeamName { get { return _teamName; } set { _teamName = value; } }
At this point, we could just use the following attribute to our client code (see ObjectViewer for the full source files):
[AssemblyTeam("MyTeam")]
Unfortunately, this assembly could be used anywhere, be it an assembly, class, method, property, and so on. It would be useful if we could specify what pieces of code this attribute could be used to annotate, which is where the AttributeUsageAttribute class comes in. It may seem a bit odd, but you can use this attribute to specify where your attribute can be used. For our attribute, we want to say that it is an assembly level attribute, so we specify that the AttributeTargets is an assembly:
[AttributeUsage(AttributeTargets.Assembly)]
Putting it all together, our class now looks like this:
[AttributeUsage(AttributeTargets.Assembly)] public class AssemblyTeamAttribute : Attribute { public AssemblyTeamAttribute(string teamName) { _teamName = teamName; } string _teamName; public string TeamName { get { return _teamName; } set { _teamName = value; } } }
We can now use it to annotate our assembly (in AssemblyInfo.cs) (see ObjectViewer for the full source files):
[assembly: AssemblyTeam("Core Services")]
When we look at our assembly using a tool such as ILDASM.exe, we can now see which team is responsible for the code by looking in the manifest:
.custom instance void ObjectLibrary.AssemblyTeamAttribute:: .ctor(string) = ( 01 00 0D 43 6F 72 65 20 53 65 72 76 69 63 65 73 // ...Core Services 00 00 )