Visual Studio .NET 的面向切面编程插件






4.50/5 (12投票s)
2003年12月8日
4分钟阅读

89471

1160
一个 Visual Studio 插件,为 .NET 语言(C#, VB.Net, J#)提供面向切面编程功能。
引言
你可能听说过面向切面编程 (AOP),它是一种新的编程技术,可以让你编写易于理解、维护、重用和演进的代码。
目前 AOP 规范的主流实现是 AspectJ(TM),它是 Java 语言的一个扩展,允许开发人员表达 AOP 术语。
AopDotNetAddIn 是一个 Visual Studio 插件(附在本文章中),它对某些 AOP 规范进行了简单的实现。通过使用这个插件,你可以使用你喜欢的 .NET 语言(C#, VB.NET 或 J#)编写 AOP 程序,而无需学习任何新的概念或构造。
在本文中,我将向你展示如何使用这个插件来开发一个面向切面实现的观察者模式。
观察者模式示例演练
在这个示例中,我们有一个简单的窗体 SubjectForm
,它充当主题。我们还有两个窗体 ObserverForm1
和 ObserverForm2
,它们充当观察者。观察者将对观察 SubjectForm
的 BackColor
变化感兴趣。
在 SubjectForm
中,我们有一个带有 Red、Green、Blue 值的组合框。你应该从列表中选择一个颜色,然后单击“更改颜色”按钮,将 SubjectForm
的 BackColor
更改为组合框中选择的相应颜色。
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
为了开始编写模式代码,我们首先编写主题观察者协议。
Public Interface Subject
Sub UpdateObservers()
Sub AddObserver(ByVal ob As Observer)
End Interface
Public Interface Observer
Sub UpdateObserver(ByVal note As Object)
End Interface
显然,SubjectForm
必须实现 Subject
接口,而 ObserverForm1
和 ObserverForm2
都必须实现 Observer
接口。
在 AOP 中,我们将观察者模式的功能与参与该模式的类分离开来,我们将把这些功能封装在一个名为 SubjectObserverAspect
的切面中。
选择“项目”->“添加新项”,然后在列表中选择“切面”(安装 AopDotNetAddIn 后应该能看到此项),将此切面命名为 SubjectObserverAspect
。
一个派生自 AspectLib.Aspect
的类 SubjectObserverAspect
将被添加到你的项目中,同时还会添加一个 XML 文件 aspectDescriptor.xml。
Public Class SubjectObserverAspect
Inherits AspectLib.Aspect
End Class
编写切面代码
正如我们所说,这个切面将包含观察者和主题的功能。首先实现主题功能,将以下代码添加到 SubjectObserverAspect
切面中。
#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
主题应该有一个所有观察者的列表,所以我们有 ArrayList
Observers
。AddObserver
函数的实现会将提供的观察者添加到 Observers
数组中。UpdateObservers
函数将遍历 Observers
数组中的所有观察者,并调用每个观察者的 Update
方法,将背景颜色传递给它。请注意,我们向 Update
函数添加了一个类型为 SubjectForm
(subj
)的参数,这个参数使我们能够访问了解主题(例如背景颜色)所需的上下文信息。
initObservers
子程序用于将 o1 和 o2 注册为 SubjectForm
的观察者。afterEvent
子程序用于启动更新观察者。这是观察者功能的实现。
#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
此实现将应用于派生自 Form
的 ObserverForm1
和 ObserverForm2
,因此我们添加了一个类型为 Form
(obs
)的参数。
编写织入指令 (aspectDescriptor.xml)
将切面代码织入对象代码(类)由 aspectDescriptor.xml 文件决定。
<?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>
指令在 <aspect>
节点内为每个切面定义。
你可以通过在 <introductions>
节点中指定来引入新的成员和/或方法。在我们的示例中,我们指定了:
- 我们将成员
Observers
添加到SubjectForm
类。 SubjectForm
类将实现Subject
接口。ObserverForm1
和ObserverForm2
(Observer*
) 都将实现Observer
接口。
<advice>
节点代表在切入点处执行的切面实现的部分,其中切入点定义了程序执行中的特定点。
第一个 advice 指定 initObserves
方法将在 SubjectForm_Load
方法之后执行(该方法具有任何访问修饰符、任何返回类型,并且在 SubjectForm
类中)。
第二个 advice 指定 afterEvent
方法将在 Button1_Click
方法之后执行(该方法具有任何访问修饰符、任何返回类型,并且在 SubjectForm
类中)。
运行示例
要运行此示例,请选择“生成”->“织入并运行”。背景
在此 处 阅读更多关于 AopDotNetAddIn 的信息。