C# and Aspect Oriented Programming

One common question I've heard recently is “Are there any plans to add AOP support to C#?”

We don't currently have any plans to add AOP into the language.

My current thinking - and I'm not speaking for the whole design team now, though I think my position is at least somewhat representative - is that the scenarios that are mentioned around AOP don't justify the inclusion of new language features. One of my concerns is that AOP adds a whole new level of complexity to reading code, in that the code that is executed in a method isn't all in the method. The scenarios I've seen listed are around logging and monitoring.

So, I think it's fair to say that we're in a “wait and see” attitude on this one. If there are compelling scenarios in this area, I'd like to know about them.

Comments (23)

  1. Nikolay Botev says:

    One scenario I can think about right away is transactions (one of the most boasted examples by Marc Fleury from JBoss)

  2. John Rusk says:

    I’m no expert on AOP, but the main examples I’ve seen are things like logging – where you have to do something at the start and end of a method.

    I’d imagine that there’s some scope for anonymous delegates to help with some of those things. E.g. something like this (syntax might not be quite right, since I haven’t worked with Whidbey preview releases yet)…

    public void SomeMethodThatNeedsLogging()




    //this is the real body of the method,

    //i.e. the stuff that we want to log



    I.e. The code we want to execute is all wrapped up in an anonymous delegate, which is passed to a routine on our Logger object. The logger logs the start of the operation, invokes the delegate, and then logs the end.

    While not as powerful as real AOP, this seems to accomplish the same effect as some of the more common AOP examples…

    Of course, it would be nicer to have some kind of magic attribute syntax to accomplish the same thing. E.g.


    public void MyMethod()


    //code goes here


    But that would require some funky compiler support to wrap up MyMethod in a delegate and automatically pass it to a method on the class LogThisMethodAttribute.

  3. Eric Newton says:

    Josh Rusk: you could use attributes and derive your "loggable" objects from ContextBound object, create a sink and intercept method calls, searching for the LoggingAttribute.

    Thats the beauty of ContextBoundObject

    One thing to EricGu: I wish ContextBoundObject itself had virtual methods that could be overriden for simpler interception, instead of having to create a ContextBoundAttribute but I’m sure there’s a good reason

  4. Thomas Eyde says:

    If functions were first class objects, we could add listeners to them, like BeforeInvoke and AfterInvoke:

    public class MyClass {

    public MyClass() {

    Execute.AfterInvoke += new LogHandler(Log);


    public void Execute() {…}

    private void Log(Function f) {…}


  5. AOP is certainly a very useful concept that should be supported by further MS products.

    I think that it should be supported at IDE level and not at langage level. By IDE level, I mean that a VS project could accept some kind of ‘AspectJ alike’ syntax. With this syntax, developers could provide some rules (CLS relative and not C# or VB.NET relative) to weave code.

    These rules would allow the compiler to weave IL instructions. A ‘must have’ functionality would be that the IDE could display and debug the weaved code in sources (maybe with a special background color). That’s why I think it should be an IDE feature. Without this kind of facilities, it is tough to anticipate AOP effects.

  6. John Rusk says:

    Thanks Eric (Newton). I’ll have to find some time to try that approach, it looks interesting.

  7. Jonathan says:

    I am a believer in some of the *results* of code weaving, but not in the known implementations. Static or dynamic woven code can stay in the clouds as far as I’m concerned, there are just too many downsides. Type A after weaving looks like Type B – what for!

    However there is a case to be made for the intervention philosophy. I am keen on Type Safe Runtime Intervention. (my own idea of "weaving")

    There is a geniune need for structural elements to *dissolve* into an application without us having to add code snippets manually like today or through weaving. From a .NET framework pov, we need "intervention" to make it possible to communicate our transparent ideas.

    I believe in a somewhat altered view of the Context approach and it can help us get to the next point – IF.

    ContextBoundObject and all the ObjectSink and other attributes merged into System.Runtime.CompilerServices System.Runtime.*Intervention*

    as a robust way of informing the compiler of our needs of execution. Work would be needed at compiler and runtime levels.

    The compiler level would hook the known elements into the graph, while the runtime would supply the dynamic hook. The jury is out on what the Context would be, but I could just as well invoke Activator.CreateInstance(Context) when desired.

    I see the contents of the Namespace as








    Configuration options within App.Config

    In effect – we get a different approach to ContextBoundObject plus a bit more, to intervene and replace IMessage, IMethodReturnMessage as we see fit. All this can be done in a Type safe way, and we benefit from being able to intervene and add to the flow and execution. This is where we can add compiled code based on Interfaces, such as logging and so forth. It would be Type safe.

    To conclude, why would we want to intervene?

    To separate structural code, context code – define it, reuse it and change it for aspects such as





    -Filtering , formatting Data

    -Providing Custom Experiences

    for Groups, Roles, Users, Other Settings

    -Cumbersome Localization tweaks

    -Resolving/intervening on Assemblies (location, version, culture), Types, Members

    I like what Thomas Eyde said about adding eventlisteners to members. Its another approach that fits well with my notion of Intervention.

    ContextBoundObject is the poor mans answer, it needs a bit of help. 😉

  8. "One of my concerns is that AOP adds a whole new level of complexity to reading code, in that the code that is executed in a method isn’t all in the method."

    Partial Classes do the same for classes. Without the IDE you can get totally lost.

    If you decide to add AOP, you can always cover for it with a good IDE.

  9. Tim Munro says:

    Using the capabilities endowed by deriving from ContextBoundObject is indeed a way to implement AOP like functionality. However my issues with this solution are two fold:

    1) I don’t always want, or in deed am able to inherit from ContextBoundObject.

    2) The overhead incurred during construction and method invocation are both significant i.e. you wouldn’t want all your calls to incur this penalty.

    With regards to the applications of AOP I think that, in addition to the areas mentioned above (logging etc.), persistence and design by contract are both good candidates for making use of this technique.

    On the subject of the increase in complexity due to the introduction of aspects, I think that with appropriate tool support this shouldn’t be too much of an issue.

    One thing I think that could be a good half way house is the use of attributes to identify methods to be intercepted (as mentioned above).

    This isn’t true AOP as the code itself has to be decorated to implement the functionality (Aspects should really be completely orthogonal to the rest of the code), but it would provide a partial answer. Especially to my two pet interests 🙂

  10. Tim Munro says:

    I also meant to say that I liked the idea of being able to attach event listners to methods as suggested by Thomas Eyde.

  11. Jonathan says:

    Ja, I hope I made that clear.

    My notion of System.Runtime.Intervention is a halfway house.

    Deriving from ContextBoundObject is the dead weight as Tim Munroe said, why should we?.

    Like Tim, I have a pet project.

    My pet project http://agileopensource.net is a form of it (but where currently I am also compiling the classes which substitute compiled Types).

    Its an experiment, to see how much work is involved, what it needs and how it should work.

    IF only:

    By not requiring the ContextBoundObject, I am free to continue deriving from my own model.

    And the compiler only throws the switch for runtime intervention when the attribute is found, limiting the penalty.

  12. Jonathan says:

    I just wanted to add, that the discussion from my post that mentioned the Accessors on objects is in a similar vein.


  13. jaybaz [MS] says:

    Thomas said: "If functions were first class objects, we could add listeners to them"

    See this series of blog posts for one way to make this happen. It’s not exactly lightweight, but I hope it’s interesting:


  14. Eric Newton says:

    i would like to see some compiler-executed code too, i guess like C macros? ug… i know that’ll reintroduce a whole lot of wierdness to compiled code

    theres gotta be a satisfactory compromise, short of "C# w/AOP language elements"

  15. Forgive my ignorance, but I though attributes provided AOP?

  16. Sam Wilson says:

    For the most part, it seems like AOP is beneficial for implementing "runtime environment" services (logging, monitoring, transactions, etc.). But I have an example situation which could benefit from something similar.

    Quick Point: I’ve examined using ContextBoundObjects, but I’m bothered by the need to inherit from this class. It would have been much better if this had been an interface rather than a class. The standard library could have provided a simple implementation that could either have been extended or delegated to in cases where you need to inherit from a separate class. In the end to get around this, objects will have to implement their context-bound portion as an per-instance singleton inner-class that extends from ContextBoundObject and is delegated to as needed. That’s ugly.

    Anyhow, my example…

    I have a simple production system that performs operations on data items based on their "state" and "type". For each (state,type) combination there is a different handler method that is supposed to perform the appropriate logic on an item. So (in "shorthand")…

    struct Item {

    string state;

    string itemType;


    interface ItemHandler {

    void handleItem(Item item);


    class ProductionSystemStateMachine {

    void addState(string itemType, string state, ItemHandler handler) {

    /* …. */


    ItemHandler getNextItemHandler(Item item) {

    /* …. */



    class ProductionSystem {

    ProductionSystemStateMachine sm;

    public static void processItem(Item item) {

    ItemHandler handler = null

    while((handler = sm.getNextItemHandler(item)) != null) {





    Obviously, very shorthand, but you get the idea. Anyhow, I use this production system in a number of different places in my system to provide for rule-based logic. I have a particular case in which a number of the entries need to exhibit the same type of error handler, as in:

    MyItemHandlerA : ItemHandler {

    void handleItem(Item item) {

    try {



    catch(Exception e) {





    Obviously, this can be handled lots of different ways (a shared delegate method, a base class that provides the standard behaviour in a closed method that calls a virtual method implemented by the children). But it’d be pretty clean if I could just say something like this:

    class MyItemHandlerA : ItemHandler {


    public void handleItem(Item item) {




    An interception-based approach would be an interesting way to provide for shared-code on a method-by-method basis. It is an improvement over the base-class approach in that it doesn’t affect the inheritance model (ContextBoundObjects being a bad example).

    Of course, the argument about "the code that is executed in a method isn’t all in the method" applies to both the base-class an interception models. I don’t see how one is better or worse than the other from a readability standpoint as both would be labeled.

Skip to main content