Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

An add-in for Aspect Oriented Programming in Visual Studio.NET

0.00/5 (No votes)
7 Dec 2003 1  
A Visual Studio AddIn that provides the aspect oriented capabilities to the .NET languages (C#,VB.Net,J#)

Introduction

Probably you've heard of Aspect Oriented Programming (AOP) , it's a new programming technique that enables you to write code that is easy to understand, maintain, reuse and evolve.

The current dominant Implementation of the AOP specification is AspectJ(TM) an extension to the java language that enables developers to express AOP terminology.

AopDotNetAddIn is a Visual Studio AddIn (attached to this article) that is a simple implementation of some AOP specifications , and by using this addin you can write AOP programs using your favorite .NET language ( C#, VB.NET or J#) you will need not learn any new concepts or constructs to use it.

In this article I'll show you how to use this addin to develop an aspect oriented implementation of the observer pattern.

Observer Pattern Sample Walkthrough

In this sample we have a simple form SubjectForm that acts as a subject. and we have also two forms that act as observers ObserverForm1 and ObserverForm2 the observers will be interested in observing the change of the BackColor of the SubjectForm .

In the SubjectForm we have a comboBox with the values Red, Green, Blue you should choose a color from the list and click the Button ChangeColor to change the BackColor of the SubjectForm to the corresponding Color selected in the comboBox.

Public Class SubjectForm
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "
.
.
.
#End Region

    Public o1 As New ObserverForm1
    Public o2 As New ObserverForm2
    Private Sub Button1_Click(ByVal sender As System.Object, _
          ByVal e As System.EventArgs) Handles Button1.Click
        Dim curColor As String = ComboBox1.SelectedItem
        Select Case curColor
            Case "Red"
                Me.BackColor = Color.Red
            Case "Green"
                Me.BackColor = Color.Green
            Case "Blue"
                Me.BackColor = Color.Blue
        End Select
    End Sub

    Private Sub SubjectForm_Load(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles MyBase.Load
        Me.o1.Location = New Point(Me.Location.X + Me.Width, _
             Me.Location.Y + Me.Height)
        Me.o1.Show()
        Me.o2.Location = New Point(Me.Location.X - Me.Width, _
             Me.Location.Y + Me.Height)
        Me.o2.Show()
    End Sub
End Class

To start coding the pattern let's first write the subject observer protocols.

Public Interface Subject
    Sub UpdateObservers()
    Sub AddObserver(ByVal ob As Observer)
End Interface

Public Interface Observer
    Sub UpdateObserver(ByVal note As Object)
End Interface

Obviously the SubjectForm must implement the Subject interface and both ObserverForm1 and ObserverForm2 must implement the Observer interface.

In AOP we separate the Functionality of the Observer Pattern from the classes participating in this pattern, we will encapsulate this functionality in an aspect named SubjectObserverAspect .

Choose Project->Add New Item then choose Aspect from the items in the list (you should see this item after you install the the AopDotNetAddIn), name this Aspect SubjectObserverAspect .

A class SubjectObserverAspect derived from AspectLib.Aspect will be added to your project also an xml file aspectDescriptor.xml will be added

Public Class SubjectObserverAspect
     Inherits AspectLib.Aspect
             
End Class

Coding the Aspect

As we said this aspect will contain the functionality of both the observer and the subject. Starting with the subject functionality add the following code to the SubjectObserverAspect aspect

#Region "Subject Functionality"
        
    Public Observers As New ArrayList

    Public Sub AddObserver(ByVal ob As Observer)
        Observers.Add(ob)
    End Sub

    Public Sub UpdateObservers(ByVal subj As SubjectForm)
        Dim ob As Observer
        For Each ob In Observers
            ob.Update(subj.BackColor)
        Next
    End Sub
    
    Public Sub initObservers(ByVal f As SubjectForm)
        f.AddObserver(f.o1)
        f.AddObserver(f.o2)
    End Sub

    Public Sub afterEvent(ByVal subj As Subject)
        subj.UpdateObservers()
    End Sub
#End Region    

A subject should have a list of all its observers so we have the ArrayList Observers, the implementation of the function AddObserver would add the supplied observer to the Observers Array. The UpdateObservers function will loop over all the observers in the Observers array and call the Update method of each one passing it the background color, note that we added an argument of type SubjectForm (subj) to the Update function, this argument enables us to access the context information we need to know about the Subject (like the background color).

The initObservers sub is where we register o1 and o2 as observers of the SubjectForm. The afterEvent sub is used to start updating the observers. And here is the implementation of the observer functionality.

#Region "Observer Functionality"

    Public Sub UpdateObserver(ByVal obs As Form, ByVal note As Object)
        Dim c As Color = CType(note, Color)
        obs.BackColor = c
    End Sub

#End Region    

This implementation will be applied to both ObserverForm1 and ObserverForm2 which derive from Form so we added an argument of type Form (obs)

Writing the Weave Instructions (aspectDescriptor.xml)

The weaving the aspect code into the object code (the classes) is determined by the aspectDescriptor.xml file

<?xml version="1.0" encoding="utf-8"?>
<aspects>
    <aspect name="SubjectObserverAspect" 
         code="SubjectObserverAspect.vb" weave="true">
        <advices>
            <advice type="after">
                <method name="initObservers" />
                <pointcut>
                    <execution>
                        <method name="SubjectForm_Load" 
                           class="SubjectForm" access="*" return="*"/>
                    </execution>
                </pointcut>
            </advice>
            <advice type="after">
                <method name="afterEvent" />
                <pointcut>
                    <execution>
                        <method name="Button1_Click" 
                              class="SubjectForm" access="*" return="*" />
                    </execution>
                </pointcut>
            </advice>
        </advices>
        <introductions>
            <member name="Observers" introduceto="SubjectForm" />
            <interface name="Subject" introduceto="SubjectForm" />
            <interface name="Observer" introduceto="Observer*" />
        </introductions>
    </aspect>
</aspects>

The instructions are defined for each aspect inside the <aspect> node.

You can introduce new member and/or methods to your classes by specifying them in the <introductions> node. In our example we specified that:

  • we will add the member Observers to the SubjectForm Class.
  • the SubjectForm class will implement the Subject interface.
  • both ObserverForm1 and ObserverForm2 (Observer*) will implement the Observer interface.

The <advice> node represent pieces of an aspect implementation to be executed at a point-cut, where the point-cut defines specific points in a program's execution

The first advice specifies that the initObserves method will be executed after the SubjectForm_Load method ( which has any access modifier , any return type and is in the SubjectForm class)

The second advice specifies that the afterEvent method will be executed after the Button1_Click method ( which has any access modifier , any return type and is in the SubjectForm class)

Running the Sample

To run this sample choose Build->Weave and Run

Background

Read more about AopDotNetAddIn here.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here