Filtered constructor interception

Technical questions about PostSharp Laos.

Filtered constructor interception

Postby ooswald on Fri Apr 11, 2008 6:03 pm

I'd like to inject compile-time code in the Constructor of each class, but only if the class contains events decorated with the "EventPublication" attribute:

Code: Select all
public class ContactManager {
    [EventPublication("ContactManager.ContactAdded")]
    public event EventHandler<ContactEventArgs> ContactAdded;

    [EventPublication("ContactManager.ContactRemoved")]
    public event EventHandler<ContactEventArgs> ContactRemoved;

    public ContactManager() {
        // TODO: let PostSharp inject this ONCE
        [b]EventInspector.Register[/b](this);
    }
}

Can that be done with a single [assembly: EventBusAspect] statement? How would you implement that?
ooswald
 
Posts: 2
Joined: Fri Apr 11, 2008 4:57 pm
Full Name: Olivier Oswald
Company: Pelagon

Re: Filtered constructor interception

Postby gfraiteur on Sat Apr 12, 2008 9:12 am

There is a single aspect allowing to inject something "safely" in the constructor (with the guarantee that the code is executed only once even in case of cascaded constructor call): it is the CompositionAspect.

In your case, you could define an interface (even empty), for instance IEventPublisher. The aspect will implement the interface. The trick is that the constructor invokes a method of this aspect; this method should create the implementation of the interface. And you can use this method to perform some initializations as well.

So it's like a workaround currently, but maybe you can even expose some useful semantics in your interface IEventPublisher, for instance:

Code: Select all
interface IEventPublisher
{
string[] GetPublishedEvents();
void AddHandler( string eventName, EventHandler handler );
void RemoveHandler( string eventName, EventHandler handler );
}


An example of project using this technique is http://code.google.com/p/postsharp4spring/.

Finally your assembly-level custom attribute will be a CompoundAspect and will iterate all types and all events for the EventPublication custom attributes, then add a single instance of the composition aspect per type.

A better alternative is to derive EventPublication from CompoundAspect and do basically the same thing (use a static Dictionary<Type,MyAspect> to to take track of aspect instances you already processed).

Good luck!

Gael
Gael Fraiteur, project leader
got good support? consider donating to the project.
gfraiteur
Site Admin
 
Posts: 674
Joined: Tue Dec 18, 2007 3:09 pm
Full Name: Gael Fraiteur
Company: postsharp.org

Re: Filtered constructor interception

Postby ooswald on Mon Apr 14, 2008 6:07 pm

While the first method works fine, I'm prefering the second approach. However, I'm unable to implement it :( Just for my understanding: instead of decorating events AND classes

Code: Select all
[EventBusAwareAspect]
public class ContactManager {
    [EventPublication("ContactManager.ContactAdded")]
    public event EventHandler<ContactEventArgs> ContactAdded;
    ...
}

I would be able to declare my class without the EventBusAwareAspect attribute and the PostSharp magic would make sure that all classes with an EventPublication decorated event would have some code inserted into the constructor?
ooswald
 
Posts: 2
Joined: Fri Apr 11, 2008 4:57 pm
Full Name: Olivier Oswald
Company: Pelagon

Re: Filtered constructor interception

Postby gfraiteur on Mon Apr 14, 2008 8:56 pm

Well, as I said, derive your EventPublication class from CompoundAspect and add instances of the EventBusAwareAspect class from your CompoundAspect. You can even make your EventBusAwareAspect class internal.

The only trick is to have no more than one EventBusAwareAspect instance per type, but you can solve that problem using a static field containing a Dictionary<Type,EventBusAwareAspect>.

Gael
Gael Fraiteur, project leader
got good support? consider donating to the project.
gfraiteur
Site Admin
 
Posts: 674
Joined: Tue Dec 18, 2007 3:09 pm
Full Name: Gael Fraiteur
Company: postsharp.org


Return to PostSharp Laos