Filtered constructor interception
4 posts • Page 1 of 1
Filtered constructor interception
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:
Can that be done with a single [assembly: EventBusAspect] statement? How would you implement that?
- 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
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:
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
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.
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
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
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?
- 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
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
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.
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
4 posts • Page 1 of 1