Is it possible to do Aspect Oriented Programming in Delphi? I would be interested in native support as well as third party solutions.
I don't have a specific problem I want to solve with AOP, but am simply interested in studying AOP.
aopdelphi
Is it possible to do Aspect Oriented Programming in Delphi? I would be interested in native support as well as third party solutions.
I don't have a specific problem I want to solve with AOP, but am simply interested in studying AOP.
Aspect Oriented Programming is so much more than just logging, reporting et cetera, as you will see if you have a look at PostSharp's web site. Personally I haven't done so much static IL weaving, mostly dynamic IL generation to create AOP interceptors and when doing so I have mostly been using it to wrap and intercept resolves from inversion of control containers.
AOP can improve exception handling, improve tracing, improve transaction interception.
NHibernate for example has a sort of AOP, even though it's static at compile-time in terms of simple event handlers; but for certain events in the engine you can attach interceptors (aka aspects, the events being the point-cuts etc) -- I use this to inject, using IoC business entities into my domain objects.
Powerful AOP-frameworks allow you to generalize and even more powerful allow you to generalize w/o overhead at runtime; in principle you have a few different ways of doing it:
(0). (not really) "pre-processor" AOP aka templates in C++, ifdefs etc
Usages in transactions Have a look at Castle.Facilities.AutomaticTransactionManagement.TransactionFacility for a nice way of handling transactions using AOP and the intercepting abilities of DynamicProxy2. The transaction facility integrated with System.Transcations and System.EnterpriseServices is you are using the distributed transaction coordinator (COM-component) for managing transactions. Also, there are multiple examples of p/invoke into the kernel to take care of the TxF and TxR components of the Vista-kernel (aka Server 2008) which allow you to use transactions on NTFS and on the registry, thereby making sure CRUD you do is ACID, which also nicely integrates with System.Transactions for creating nested transactions.
Usages in invariant verification You can also use them for design by contract, by appending some attributes to your parameters.
public void PerformOperation([NotNull, NotEmpty] string value) {
// use string
[NotNull] return new string(' ', 5); // can return with attributes as well
}
The problem with this at the moment is the overhead of attaching this meta-data and checking it at runtime. However, you could specify the constraint-checking aspect only to be applied when you're compiling with DEBUG and then this meta data-wouldn't lead to much deterioration in performance.
If you are looking to get into axiomatic proofs, have a look at Sing#/Spec# instead, since that's more formal and the work is done by the compiler.
Things to be aware of The most important point to be aware of is that if a concern, i.e. some piece of code that runs before or after your method is altering the control-flow, possibly returning an unexpected type, returning too early or in general doesn't behave along the intents of the method you were calling you may get errors which are hard to debug.
Also, beware of the throwing of exceptions from attributes, because you never know when or from what assembly, reflection occurrs; the reflection on your attribute may not happen when you expect to. This happened to myself when I was attaching types in attributes and carefully checking them.
Also beware of the fact that you're opening a possible attack vector in adding global "point-cuts" which, if someone gets access to, can be used to redirect large portions of your system.
Other frameworks If you are interested in learning more about AOP in general I suggest you check out Rickard Öberg's presentations on Qi4J, it's a very good framework in Java for AOP (java has slightly different object-inherited semantics though which makes a wee bit tricker to use in C#/F#/Nermle/Boo whatever.
AOP + AddIns Another interesting possibility in using aspect oriented programming with runtime-generated assemblies such as those dynamicproxy2 creates, is that you can also use them to wrap objects that cross application boundaries, thereby simplifying the creation of a add-in-pipeline. I had secretly hoped that Microsoft would use this when they created their AddIn-framework for 3.5, but they chose to go the static code-gen way unfortunately, leading a a rather big overhead in creating add-ins, for the developer. The problem is that a type loaded for "more than reflection" into an AppDomain can't be unloaded again unless the complete AppDomain is unloaded, so you need 1) to reflect on the plugin without loading it to see what it is capable of unless you allow for lots of manual meta-data to be written or generated (and believe in that) and 2) some object to hold the handle to your object so that it's not GCed and you don't know the type (hence the IContract assembly and AddInHandle-class) -- this could probably be done in a nice way with a dynamic proxy/AOP.
Using AOP for global garbage collection ... in a distributed system running on linux/windows on the common language infrastructure. The paper was a bit hard to download so I uploaded it to my server so I know where it is.
Post Scriptum (If you are using a non-standard language on the CLR and not the DLR IL-weaving might create non-standards compliant code. Especially interesting for F#, I think, because the use a lot of non-standard code to great benefit of the language (tuples say) -- you could mark your assembly with [assembly: CLSCompliant] if you want to get compile-time warnings of this.)
I'd say that a view shouldn't contain much programming (or nothing at all). The idea of using AOP (or a la AOP) in a place where the P is forbidden doesn't look nice.
Let's design it in a different way. Usually views have some control keywords to do the basic stuff: conditions and loops. More intelligence and I'd say that you're mixing the controller role there.
So the if (user.CanSeeSomeData)
you put there, if it is in fact a simple flag. It's the way views should be.
When you were building the modelview object (the container where you put the information for the view). You could have used AOP to initialize/set that information with a nice attribute in that property for example.
You could ask for attributes instead of "ifs"
[UserCanSeeData]
<%=Html.TextBox("MyTextBox") %>
This looks like syntactic sugar, not real AOP. Any attempt to say that UserCanSeeData should have more than an if (like a database access to check user priviledges), is an attempt to move controller code into the view.
Best Answer
AOP depends on two things:
This is commonly referred to as code weaving. It is a specialization within the larger study of program transformation.
JIT compiled languages have more options for implementing code weaving than statically compiled programs because more information is retained in the bytecode/IL. They also support reflection, which offers the ability to manipulate code at runtime.
Delphi.NET and Prism have the same access to these capabilities as any other .NET language.
There are two AOP frameworks for Delphi Win32 that I'm aware of. The first is MeAOP, which has already been mentioned. The second is Infra. Both projects take a similar approach to AOP. They use a combination of RTTI and clever pointer manipulation to intercept method calls so you can run additional code before or after the method call. You define your cross-cutting feature as a subclass of the framework's AOP class. You register the methods you want intercepted by passing the method name as a string argument to the AOP framework.
Both frameworks are still actively developed and are actually larger in scope than just AOP. Unfortunately documentation is somewhat sparse (and in Infra's case mostly in Portuguese)
Another project attempted AOP through source code weaving back in 2004 with some success. Basically they built an aspect weaver on top of a general purpose program transformation tool called DMS and used it to inject code into delphi source files prior to compilation. Their aspect oriented language was primarily influenced by AspectJ.
http://www.gray-area.org/Research/GenAWeave/ has links to the original paper and presentation as well as some videos of the transformation process.
It may also be possible to use runtime code instrumentation to accomplish this as well. Its a technique used by some profilers to inject counters and stack traces into running code without modifying the original source. A similar technique could be used to inject crosscutting concerns into a statically compiled executable. The PinTool project is a good example of this.