Thomas Haller
Thomas Haller

Reputation: 199

AOP Pre-compile time weaving?

I have been playing along with AOP for years, but didnt become 100% satisfied with the solutions. AOP Frameworks with runtime weaving, like Spring.AOP, cannot change the interface of a class. With post compile time Frameworks like Postsharp (anyone knows someone else ?) you can. Check this sample out, it adds INotifyPropertyChanged implementation to your class. -> http://www.postsharp.net/model/inotifypropertychanged

This AOP feature is really great, but you run in troubles very soon... If you want to access the new Interface within the hosting assembly, you cannot compile, because the interface is added AFTER compilation. so you get a "PropertyChanged is not defined"-error. So you have to ugly workaround this, by seperating the classes into another assembly, so you can use those AOP advantages. I remember, i ran into the same "Post compile time"-troubles using a T4-Template that generates source code, based on the reflected infos of a assembly. OK so post compile time is sometimes too late...

What i am looking for is a solution, where the source code of the class is parsed via a visual studio user defined tool, und then generates the code in a C# file, in a partial class. (so all AOP applied classes have to be partial)

So its kind of "Pre-Compile-Time AOP". This should definitly be possible, and could be done via using NRefactory as Code Parser. Furthermore, Visual Studio would like this much more, than a post-compile modification.

So this solution eliminates disadvantages of post compile time weavers. but does not give you all the features of AOP. But together with an AOP-Framework, this should be awsome.

Does anyone know a framework like this, or a discussion ?! what do you think ?

kind regards, thomas

Upvotes: 5

Views: 2434

Answers (3)

Philip Pittle
Philip Pittle

Reputation: 12305

What your are looking for is pMixins. It's still in beta, but it does exactly what you are looking for: design-time weaving. AOP code is generated into a partial code-behind class so it's available at design-time.

So this means you can do this in one file and the compiler is happy, visual studio is happy, resharper is happy:

Define an interface:

public interface ISomeInterface
{
    void SomeMethod();
}

Create an implementation of the interface (I call this a Mixin):

public class SomeInterfaceImplementation : ISomeInterface
{
    public void SomeMethod()
    {
        //implementation
    }
}

Define a Target file (which will consume the Mixin):

[pMixin(Mixin = typeof(SomeInterfaceImplementation))]
public partial class Target { }

Let's create a utility class that works with SomeInterface and SomeInterfaceImplementation:

public class Utility
{
    public void DoSomeWorkOnSomeInterface(ISomeInterface obj)
    {
        obj.SomeMethod();
    }

    public void DoSomeWorkOnImplementation(SomeInterfaceImplementation obj)
    {
        obj.SomeMethod();
    }
}

And now let's see it all work together:

class Program
{
    private static void Main(string[] args)
    {
        //Call the mixed in method
        new Target().SomeMethod();

        //Target implements ISomeInterface is code-behind
        new Utility().DoSomeWorkOnSomeInterface(new Target());

        //Target has an implicit conversion operator to 
        //SomeInterfaceImplementation in code-behind
        new Utility().DoSomeWorkOnImplementation(new Target());
    }
}

The reason this works is because as soon as you save the file, the pMixins code generator immediately does design-time weaving and updates the code-behind file. It adds the SomeMethod directly to Target, updates Target's class definition to implement ISomeInterface and creates conversion operators.

Disclosure: I am on the pMixins development team.

Upvotes: 1

Tyler Brinks
Tyler Brinks

Reputation: 1201

since you and I have already been corresponding on using SNAP as a viable alternative, I thought I'd post a summary of our discussion here for the benefit of those who are looking for a similar solution.

In short, SNAP provides a runtime AOP framework that doesn't change your code in any way. There's no post-compile step, just runtime interception which is predictable and easy to use.

Upvotes: 1

Gael Fraiteur
Gael Fraiteur

Reputation: 6857

In the case of PostSharp, you can access an interface introduced at post-compile-time by using the method Post.Cast, which is a kind of cast operator that is verified at post-compile-time. See http://doc.postsharp.net/postsharp-3.0/Content.aspx/PostSharp-3.0.chm/html/M_PostSharp_Post_Cast__2.htm for documentation.

Upvotes: 0

Related Questions