With PostSharp, you can easily write and apply custom attributes that add new behaviors to your code - tracing, thread management, exception handling, data binding, and much more.
PostSharp is the number one choice for aspect-oriented programming on the Microsoft .NET platform.
Rather than explaining complicated theory, we'll show you. Here are five aspects:
public class TraceAttribute : OnMethodBoundaryAspect { public override void OnEntry(MethodExecutionEventArgs eventArgs) { Trace.TraceInformation("Entering {0}.", eventArgs.Method); } public override void OnExit(MethodExecutionEventArgs eventArgs) { Trace.TraceInformation("Leaving {0}.", eventArgs.Method); } }
public class AsyncAttribute : OnMethodInvocationAspect { public override void OnInvocation(MethodInvocationEventArgs eventArgs) { ThreadPool.QueueUserWorkItem(delegate { eventArgs.Proceed(); }); } }
public class GuiThreadAttribute : OnMethodInvocationAspect { public override void OnInvocation(MethodInvocationEventArgs eventArgs) { DispatcherObject dispatcherObject = (DispatcherObject)eventArgs.Delegate.Target; if (dispatcherObject.CheckAccess()) eventArgs.Proceed(); else dispatcherObject.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => eventArgs.Proceed())); } }
public class ExceptionDialogAttribute : OnExceptionAspect { public override void OnException(MethodExecutionEventArgs eventArgs) { string message = eventArgs.Exception.Message; Window window = Window.GetWindow((DependencyObject)eventArgs.Instance); MessageBox.Show(window, message, "Exception"); eventArgs.FlowBehavior = FlowBehavior.Continue; } }
public class CacheAttribute : OnMethodInvocationAspect { public override void OnInvocation(MethodInvocationEventArgs eventArgs) { object value; string key = // Compute the cache key (details omitted). if (!cache.TryGetValue(key, out value)) { lock ( this ) { if (!cache.TryGetValue(key, out value)) { eventArgs.Proceed(); value = eventArgs.ReturnValue; cache.Add(key, value); return; } } } eventArgs.ReturnValue = value; } }
Once you have aspects, apply them to your existing code. It's easy. Aspects are plain custom attributes. Just annotate relevant methods with the aspect:
[Trace] public void CreateCustomer(int id, string name) { /* ... */ }
You can also apply the aspects to many classes and methods in a single line, without even touching the source code of these classes.
[assembly: Trace( AttributeTargetTypes="MyApp.BusinessProcesses.*", AttributeTargetMemberAttributes = AttributeTargetElements.Public )]
The typical software project has two types of requirements: functional and technical.
You won't find technical code listed with requirements, but as all experienced developers know, your application will be unstable and unmaintainable without it. Because this technical code crosscuts the functional code at various points, it's not properly isolated in maintainable modules.
For instance, we cannot implement tracing, exception handling, thread synchronization or most other technical requirements without adding redundant code to each of the many methods requiring these behaviors.
Think of PostSharp as an extension of Visual Studio and your favorite compiler. With PostSharp:
The ultimate benefit is the reduced cost of development and maintenance. Specific benefits will appeal to developers, architects, managers, and independent software vendors in different ways.
PostSharp operates at build time: it transforms the output of the compiler and injects aspects into your code.
There is no hack: you can view the generated code in a decompiler, like Redgate Reflector. What you see is exactly what executes.