This blog has moved!

Check out www.CodeBetter.com/blogs/grant.killian

<October 2008>
SuMoTuWeThFrSa
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678


Navigation

Professional Props...

Extracurricular Props...

Subscriptions

Article Categories



Reflecting on Attributes and Metadata

This post complements a discussion we had in the ODU ITPro class the other evening; it gets into much more advanced topics than a 200 level course warrants, but for those interested folks out there, read on . .  . 

The .NET CLR (Common Language Runtime) is a bit like a cozy blanket wrapped around our business logic.  Not only is it a class loader and execution environment for our .Net types, it facilitates various forms of security, cross-language compatibility, memory management, type safety . . . and this isn’t an exhaustive list.   In fact, the CLR environment is better than just a blanket – it’s like an electric blanket with a hot chocolate machine and slippers built in!

Metadata is one of the ways the CLR achieves such a rich set of services to our .Net code.  As programmers, we can leverage this metadata to interesting ends.  If you want to follow along at home, add a button and a listbox to a windows form and include the following in the button click event (since I’m teaching a vb.net class currently, I opted for vb sample code – everything is essentially the same in c#):

Dim fileSys as New OpenFileDialog()
fileSys.Filter = "Executables ( *.exe )|*.exe|Assemblies ( *.dll )|*.dll"
fileSys.ShowDialog()
Dim assm As Reflection.Assembly = Reflection.Assembly.LoadFrom( fileSys.FileName )


The .Net Reflection namespace is a powerful mechanism for reading (and even writing!) assembly data. After calling Reflection.Assembly.LoadFrom(), our assm variable can tell us all about the assembly that we browsed to with the OpenFileDialog. Let’s add the following to our button click event code:
Dim arrTypes As Type() = assm.GetTypes()
Dim arrAttributes as Attribute()
Dim objType As Type
Dim objAtt As Attribute
Dim objCustAtt As MyAttribute ‘custom attribute


The above is just variable declarations, with the notable exception of the first line (assm.GetTypes()) where we assign all the types in the assembly to our arrTypes array. Assembly metadata contains detailed descriptions of the types our assembly exposes; Reflection, by using assm.GetTypes(), is our tool to reveal these types.
Now for the good part:

For Each objType In arrTypes
ListBox1.Items.Add( objType.FullName & " Summary" )
arrAttributes = Attribute.GetCustomAttributes( objType )
if arrAttributes.GetUpperBound( 0 ) > 0 then
For Each objAtt in arrAttributes
Try
ListBox1.Items.Add( objAtt.ToString() )
objCustAtt = CType( objAtt, MyAttribute )
ListBox1.Items.Add( "***Custom Value: " & objCustAtt.Value )
Catch

End Try
Next
End If
Next objType


Assuming we’ve got a listbox (named ListBox1), this code will interrogate the types in the assm assembly and display information about the type. If you run this sample on a .Net windows application you’ll see that there are a number of System.ComponentModel attributes at work. I won’t go into the functionality of those attributes because I want to focus on making our OWN attributes. Let’s add the following class to the project we’re creating:

<AttributeUsage( AttributeTargets.All )> _
Public Class MyAttribute
Inherits System.Attribute
private _strVal as String

Public ReadOnly Property Value as String
Get
return _strVal
End Get
End Property

Public Sub New( Value As String )
MyBase.New( )
_strVal = Value
End Sub
End Class


This is a simple example of a custom attribute with a single public property (named Value); it inherits from the System.Attribute class and uses an attribute of its own (in VB.Net, attributes are contained within < and > tags). With this class added to our project, we can include our custom attribute to any class definitions in our project as follows:

<MyAttribute( "Some Custom Data" )> _
Public Class Form1


Attributes must be on the same line as the class definition (note the line continuation character “_”).

If you run the program and select the exe that we added our custom attribute to, you’ll see the “Some Custom Data” text displayed in the listbox along with the other intrinsic .Net attributes.

Why is this significant? It allows us to extend .Net metadata and solve programming problems in different ways. .Net uses Attributes all over the place, two examples being to communicate security conditions and to control design-time behaviour of controls. In my company, we use custom attributes to map data objects to relational database objects (for ex: <DataFieldAttribute( “idProduct” ) >); this way we can decouple our object model from the database. Attributes can offer an elegant solution and, with Reflection and Metadata providing the tools, I recommend keeping an eye out for opportunities to make use of them. They aren’t always the answer, but custom attributes and Reflection are powerful enough to warrant your consideration.

posted on Tuesday, August 19, 2003 8:10 AM by grant.killian





Powered by Dot Net Junkies, by Telligent Systems