1) OnExceptionAspect
از OnExceptionAspect برای مدیریت استثناءهای متدها استفاده میشود. کار این Aspect، اضافه کردن try/catch به کدهای یک متد است و سپس فراخوانی متد OnException در صورت بروز خطایی در این بین.
using System; using System.Reflection; using PostSharp.Aspects; namespace AOP03 { public class ApplicationExceptionHandlerAspect : OnExceptionAspect { public override void OnException(MethodExecutionArgs args) { Console.WriteLine("Exception Type: {0}, StackTrace: {1}", args.Exception.GetType().Name, args.Exception.StackTrace); } public override Type GetExceptionType(MethodBase targetMethod) { return typeof(ApplicationException); } } }
نحوه استفاده از این Aspect نیز همانند مثال قسمت قبل است و جزئیات آن تفاوتی نمیکند.
2) LocationInterceptionAspect
این Aspect برخلاف سایر Aspectهایی که تاکنون بررسی کردیم، تنها در سطح خواص و فیلدهای یک کلاس عمل میکند. کار Interception در اینجا به معنای تحت کنترل قرار دادن اعمال set (پیش از فراخوانی set) و get (پیش از بازگشت مقدار) این خواص عمومی و حتی خصوصی تعریف شده است. کلمه Location در این Aspect به معنای متادیتای زمینه کاری است؛ مانند Name و FullName خواصی که مشغول به کار با آنها هستیم.
using System; using PostSharp.Aspects; namespace AOP03 { public class ObjectInitializationAspect : LocationInterceptionAspect { public override void OnGetValue(LocationInterceptionArgs args) { if (args.GetCurrentValue() == null) { Console.WriteLine("Property {0} is null.", args.LocationFullName); } } } }
برای استفاده از آن نیز کافی است تا ویژگی ObjectInitializationAspect به خاصیتی دلخواه اضافه شود.
در اینجا 4 متد args.GetCurrentValue برای دریافت مقدار جاری خاصیت، args.SetNewValue جهت تنظیم مقداری جدید، args.ProceedGetValue و args.ProceedSetValue سبب اجرای حالتهای get و set میشوند (چیزی شبیه به عملکرد اینترفیس IInterceptor که در قسمتهای قبلی بررسی کردیم).
3) EventInterceptionAspect
EventInterceptionAspect همانطور که از نام آن نیز پیدا است، در سطح رخدادهای یک کلاس عمل میکند. سه متدی که این کلاس پایه برای تحت نظر قرار دادن اعمال رویدادگردانهای یک کلاس در اختیار ما قرار میدهند شامل OnAddHandler، OnRemoveHandler و OnInvokeHandler هستند.
using PostSharp.Aspects; using System; namespace AOP03 { public class LogEventAspect : EventInterceptionAspect { public override void OnAddHandler(EventInterceptionArgs args) { Console.WriteLine("Event {0} added", args.Event.Name); args.ProceedAddHandler(); } public override void OnRemoveHandler(EventInterceptionArgs args) { Console.WriteLine("Event {0} removed", args.Event.Name); args.ProceedRemoveHandler(); } public override void OnInvokeHandler(EventInterceptionArgs args) { Console.WriteLine("Event {0} invoked", args.Event.Name); args.ProceedInvokeHandler(); } } }
مدیریت اعمال Aspects در زمان کامپایل
یکی از متدهایی که در کلیه Aspects توکار فوق قابل تحریف است، CompileTimeValidate نام دارد.
public class LoggingAspect : OnMethodBoundaryAspect { public override bool CompileTimeValidate(System.Reflection.MethodBase method) { return !method.IsStatic; }
چند نکته تکمیلی در مورد توزیع برنامههای مبتنی بر PostSharp
الف) اگر نیاز است به اسمبلیهای خود امضای دیجیتال اضافه کنید، در حالت استفاده از PostSharp به علت بازنویسی کدهای IL اسمبلی تولیدی، نیاز است حالت delay signing انتخاب شود. به این معنا که ابتدا اسمبلی به صورت متداول کامپایل میشود. سپس PostSharp کار خود را انجام داده و در نهایت با استفاده از ابزارهای اعمال امضای دیجیتال باید کار افزودن آنها در مرحله آخر انجام شود.
ب) در حال حاضر تنها برنامه Dotfuscator است که با PostSharp برای obfuscation سازگاری دارد.