Sử dụng AOP với PostSharp Framework
Posted On Saturday, September 20, 2008 at at 9:03 PM by Unknown- Spring.NET là một framework với nhiều chức năng trong đó có AOP. Nguyên tắc hoạt động của AOP trong Spring là gắn những “custom action” vào hệ thống lúc RunTime nhờ vào khả năng tùy biến rất cao của các file xml config. Có thể nói Spring.NET là framework hỗ trợ AOP mạnh nhất hiện nay. Ngoài Spring.NET còn có nhiều framework AOP khác cho .NET, trong đó mới nổi lên là PostSharp.
I. Giới thiệu PostSharp framework
- Trước hết PostSharp là một free, open-source platform để “enhance” .NET assemblies, có nghĩa là PostSharp sẽ biến đổi assemblies của bạn trong khi bạn build source code. Điều này hoàn toàn khác với AOP của Spring.NET. Spring sẽ thực hiện những biến đổi của bạn lúc runtime, còn PostSharp sẽ trực tiếp thay đổi kết quả build source code ngay lúc chương trình được compile.
- PostSharp Laos (Lightweight Aspect – Oriented Solution) là một AOP framework cho .NET developer, và theo tôi sử dụng nó tương đối đơn giản hơn AOP trong Spring. Tuy nhiên bù lại nó sẽ mất đi tính uyển chuyển như AOP trong Spring.NET. Các “advised code” sẽ phải reference đến các class Aspect của bạn, và do PostSharp modify asemblies lúc build time nên lúc build code bạn sẽ thấy hơi lâu một chút xíu.
- Thực sự thì PostSharp sẽ “transform” các .NET assemblies với dll PostSharp Laos. Với PostSharp, developer sẽ viết những “custom attributes” rồi sử dụng các Attributes này khi khai báo class/method để thêm những “custom behavior” cho code của mình. Theo như tác giả Nuvio thì PostSharp Laos là một “leading AOP solutions” cho .NET Framework như theo tôi thì chưa chắc. Tuy vậy cũng rất đáng để tìm hiểu platform này để mở rộng nhiều lựa chọn khi ta muốn lập trình AOP.
PostSharp thực sự hoạt động như thế nào?
- PostSharp là một post-compiler. Khi bạn thêm references đến những dll của PostSharp, nó sẽ tự động thêm phần code Aspect của bạn vào lúc bạn build chương trình. Có nghĩa là code chính của chương trình vẫn không đổi nhưng ouput assembly lại bị PostSharp biến đổi. PostSharp được tích hợp vào process build của MSBuild trong Visual Studio .NET 2005 và 2008, thậm chí nó được tích hợp vào bất kì IDE nào sử dụng MSBuild như SharpDevelop.
Các bạn đang xem bài viết về Sử dụng AOP với PostSharp Platform từ blog của Nguyễn Thoại (http://nthoai.blogspot.com)
- Theo như tác giả giới thiệu thì PostSharp platform có thể được sử dụng lúc Runtime như Spring AOP thay vì lúc compile nhưng tôi vẫn chưa có thời gian tìm hiểu sâu vào chức năng này. Trong phạm vi bài viết này, chúng ta sẽ tìm hiểu khái quát xem PostSharp có thể giúp gì khi muốn lập trình AOP, và làm một sample đơn giản để hiện thực điều đó.
II. Lập trình AOP với PostSharp
- Để sử dụng PostSharp, ta có hai lựa chọn. Hoặc là các bạn download installer của PostSharp và install vào máy mình. Khi đó trình Installer của PostSharp sẽ làm hết mọi việc cho ta, từ đăng kí dll của PostSharp vào hệ thống đến cả tích hợp file help của nó vào VS.NET. Khi bạn build project có sử dụng dll của PostSharp, các bước biến đổi assembly lúc runtime sẽ tự động được gọi và ta không cần quan tâm đến nó.
- Lựa chọn thứ hai là ta chỉ download các dll của PostSharp, tạo project AOP bình thường và không cần Install bất cứ cái gì vào máy. Tuy nhiên bù lại ta phải thực hiện một số thay đổi vào file “csproj” của solution để buộc PostSharp hoạt động lúc ta build chương trình. Sample trong bài viết này sẽ thực hiện theo cách này vì tôi không thích cài bất cứ cái gì vào máy trong khi có thể làm được vói cách khác.
- Download những thứ cần thiết của PostSharp ở đây: http://www.postsharp.org/download/
- Download PostSharp sample code ở đây: http://nthoaiblog.googlepages.com/SamplePostSharpAOP.zip
- Khi lập trình AOP với PostSharp, ngoài những việc linh tinh như add references, sửa file project “csproj” nếu cần thiết,.. thì ta cần 2 bước chính.
Bước 1: Tạo class Aspect
- Tạo ra class Aspect của chúng ta thực sự là ra một class Attribute. Class Aspect này sẽ phải “derived” một trong các Aspect base classes của PostSharp như: OnExceptionAspect, OnMethodBoundaryAspect, OnMethodInvocationAspect, …
- Nếu không “derived” các base class này, ta có thể implement một trong những interface tương ứng như IOnExceptionAspect, IOnMethodBoundaryAspect, IOnMethodInvocationAspect, …
- Class Attribute của ta khi implement 1 interface thích hợp sẽ có vài trò và khả năng tương ứng với interface mà nó implement. Ví dụ khi ta tạo một class Attribute implement interface OnMethodBoundaryAspect, ta sẽ phải overwrite các method như OnEntry, OnExit, … Code của method OnEntry sẽ được PostSharp compiler “gắn” vào phần đầu của bất cứ function nào được khai báo bằng Attribute ta đang tạo ra; và code của method OnExit sẽ được “gắn” vào cuối cùng của bất cứ function nào được khai báo bằng Attribute này. Khá đơn giản và khá giống với khi ta implement interface ImethodInterceptor trong Spring.NET AOP đúng không? Tôi nghĩ rằng không cần giải thích thêm thì bạn cũng biết khi implement OnExceptionAspect sẽ tạo ra một Attribute để dùng trong trường hợp nào. Trong file chm document của PostSharp có đề cập rất chi tiết từng lớp như trên và ta có thể tham khảo để tìm ra class mình cần. Bây giờ hãy xem một lớp Attribute trong sample được implement như thế nào:
[Serializable]
public sealed class AroundLoggingAttribute : OnMethodBoundaryAspect
{
private ConsoleColor _color = ConsoleColor.Green;
private ConsoleColor _currentColor = Console.ForegroundColor;
public AroundLoggingAttribute(ConsoleColor outputColor)
{
_color = outputColor;
}
public override void OnEntry(MethodExecutionEventArgs eventArgs)
{
Console.ForegroundColor = _color;
Console.WriteLine("Entering {0}.", eventArgs.Method);
Console.ForegroundColor = _currentColor;
}
public override void OnExit(MethodExecutionEventArgs eventArgs)
{
Console.ForegroundColor = _color;
Console.WriteLine("Leaving {0}.\n", eventArgs.Method);
Console.ForegroundColor = _currentColor;
}
}
public sealed class AroundLoggingAttribute : OnMethodBoundaryAspect
{
private ConsoleColor _color = ConsoleColor.Green;
private ConsoleColor _currentColor = Console.ForegroundColor;
public AroundLoggingAttribute(ConsoleColor outputColor)
{
_color = outputColor;
}
public override void OnEntry(MethodExecutionEventArgs eventArgs)
{
Console.ForegroundColor = _color;
Console.WriteLine("Entering {0}.", eventArgs.Method);
Console.ForegroundColor = _currentColor;
}
public override void OnExit(MethodExecutionEventArgs eventArgs)
{
Console.ForegroundColor = _color;
Console.WriteLine("Leaving {0}.\n", eventArgs.Method);
Console.ForegroundColor = _currentColor;
}
}
Code 1
Theo như hướng dẫn của tác giả Nuvio thì ta nên khai báo lớp là seal và sử dụng attribute Serializable. Lớp AroundLoggingAttribute đã derived từ class OnMethodBoundaryAspect. Nó implement 2 method OnEntry và OnExit, print ra console một số message với màu được dùng từ màu ở constructor. OK, bây giờ ta sẽ sang bước thứ hai
Bước 2: Viết các xử lý của chương trình, sử dụng Attribute vừa được tạo:
- Trong Sample này, tôi cũng tạo ra một lớp ServiceCommand, chỉ print ra console vài message đơn giản, mỗi method của nó được khải báo với Attribute: [AroundLogging]. Các bạn chú ý tôi có sử dụng constructor cho Attribute để sử dụng các màu khác nhau cho 2 method SayHello và SayBye.
public class ServiceCommand
{
[AroundLogging(ConsoleColor.Green)]
public void SayHello()
{
Console.WriteLine("Hello Dudes!");
}
[AroundLogging(ConsoleColor.Red)]
public void SayBye()
{
Console.WriteLine("Bye. Visit: http://nthoai.blogspot.com");
}
}
{
[AroundLogging(ConsoleColor.Green)]
public void SayHello()
{
Console.WriteLine("Hello Dudes!");
}
[AroundLogging(ConsoleColor.Red)]
public void SayBye()
{
Console.WriteLine("Bye. Visit: http://nthoai.blogspot.com");
}
}
Code 2
- Ta có thể không cần khai báo trên mỗi function, nếu ta muốn Attribute này được apply hết cho toàn bộ class thì chỉ cần khai báo một lần Attribute này cho class ServiceCommand. Thậm chí, nếu muốn apply cho toàn bộ class trong một Assembly, thì có thể modify file AssemblyInfo.cs để làm điều đó.
Bước 3: Điều chỉnh file csproj để PostSharp compiler được thêm vào quá trình build.
(Bước này sẽ không cần thiết nếu bạn sử dụng installer của PostSharp)
- Vì tôi không install PostSharp mà chỉ sử dụng những dll của platform này, tôi buộc phải chỉnh file csproj chính của solution để buộc PostSharp build và đưa Aspect AroundLogging vào assembly của ServiceCommand như đã khai báo.
- Tôi mở file PostSharpSample.ConsoleApp.csproj (đây là file project chính của solution), tìm đến dòng ở gần cuối:
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
Và thêm vào
<Import Project="..\..\buidscript\PostSharp-1.0.targets" />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\buidscript\PostSharp-1.0.targets" />
<Import Project="..\..\buidscript\PostSharp-1.0.targets" />
Hình 2
Các bạn đang xem bài viết về Sử dụng AOP với PostSharp Platform từ blog của Nguyễn Thoại (http://nthoai.blogspot.com)
- Các bạn chú ý rằng tôi sử dụng đường dẫn tương đối để chỉ đến file PostSharp-1.0.targets. Các bạn có thể copy thư mục buildscript đến một nơi nào đó trong máy, sau đó sửa lại đường dẫn này theo đường dẫn mới, reload project khi VS.NET yêu cầu, save solution, đóng solution rồi mở lại solution và build lại lần nữa để chạy được chương trình. Nếu để ý bạn sẽ thấy quá trình build sẽ hơi chậm hơn bình thường.
- Nếu vẫn chưa “clear” hoặc muốn tìm hiểu thêm những config này, hãy đọc chương đầu trong file document chm của PostSharp. Nói chung thì ta nên để thư mục chứa các file build ở một nơi nào đó trong máy, chỉ chỉnh file project lúc cần thiết là được. Và nếu muốn đơn giản hơn thì install PostSharp cho lành.
Và đây là kết quả khi chạy chương trình:
Entering void SayHello()
Hello Dudes!
Leaving void SayHello().
Entering void SayBye()
Bye. Visit: http://nthoai.blogspot.com
Leaving void SayBye().
Hình 3
Nếu bạn dùng chương trình .NET Reflector để đọc assembly thì sẽ thấy code của chúng ta đã bị sửa đổi như hình
III. Kết luận
- PostSharp có vẽ dễ sử dụng, bạn có thể viết nhiều plugin của mình để gắn vào chương trình bằng cách implement các Interface đơn giản. Tuy tác giả giới thiệu PostSharp có thể hoạt động lúc Runtime nhưng tôi vẫn chưa chắc về cái Runtime của PostSharp. Có lẽ PostSharp không flexible như AOP của Spring.NET nhưng community của PostSharp có làm các project cuả họ để kết hợp PostSharp với các framwork nổi tiếng như Spring.NET, Entity Framework, ... Nói chung có đồ free xài là vui rồi, tuy nhiên ai có lòng tốt có thể donate cho bác Nuvio ở đây: http://www.postsharp.org/donate/
Asian Models
Hot Girls VietNam
Game BlackBerry
Thiet ke web thai nguyen