Just when you thought you knew everything there was to know about Enterprise Library 3.0, we have one last surprise in store: a new application block! The Policy Injection Application Block got off to a late start, but we're making good progress now and we'll ship the first public drop in the February 2007 CTP. The final release of Enterprise Library 3.0 (scheduled for late March) will of course contain the final release.
But first things first: what the hell is this thing? The short(ish) answer is that the Policy Injection Application Block will simplify the separation of business logic from cross cutting concerns, by letting you define policies and the objects/methods they apply to in a declarative way. Each policy contains a pipeline of "handlers" that are executed before and after a policy-enabled method is called. The handlers can do whatever you want, but the most common scenario will be to implement cross-cutting concerns such as logging, validation, exception handling and authorization. By amazing coincidence, Enterprise Library already includes blocks that implement these kinds of capabilities, so our out-of-the-box handlers will be simple wrappers over existing application blocks.
For a detailed description of the design and the rationale behind it, check out Ed Jezierski's post - but to get you started, here are a few more details on how this will work. The Policy Injection Application Block will provide a special Factory class that you can use to create instances of objects that may potentially have policies defined on them. I say potentially as one of the big benefits of this block is that you can define and change the policies through configuration, so you won't actually know at compile time which objects will have policies defined. The factory will inspect the configuration and determine if a policy exists. If no such policy exists, the factory will create an instance of the requested object and return it. If a policy does exist, the factory will create a proxy (technically a transparent proxy / real proxy pair) for the object, and wire this up to the chain of handlers and ultimately the real object. To the client, the proxy looks and smells exactly like the real object, but it will have the policies injected between the proxy and the real object.
The configuration for the block will look something like this:
As you can see, each policy consists of a collection of matching rules and a collection of handlers. A matching rule is basically a predicate that defines which types and members the policy should apply to. If you specify more than one matching rule, all must apply for a policy to take effect. Out of the box we will ship matching rules that check for a specific assembly, namespace, type, method signature, or specific attributes on type or member definitions. Of course you'll also be able to write your own matching rules, should you want a policy to apply only when the moon is full or something similarly obscure. In the event that a particular class/method matches more than one policy, all of the matching policies will be executed in the order that they are defined.
Handlers are the classes that do the interesting work before and/or after a method is called. A handler is able to inspect the payload of the method call or return value, act on it, and even change it. In normal situations each handler will do its preprocessing work, invoke the next handler, wait for the call to return, do postprocessing work, and return control to the previous handler. However in certain situations a handler may decide not to call the next handler at all. One good example is an Authorization Handler. Its job is to check whether the current user is authorized to call the method. If the check shows the user is good to go, the handler will invoke the next handler in the chain. However if the user is not authorized, the handler will create an exception, package it up and send it back to the previous handler in the chain as shown below:
From the client's perspective, the result will appear identical to what would happen if the target object threw the exception itself, although in this case the exception was generated without ever calling the real object.
As I mentioned before, the handlers we will supply out of the box will be thin wrappers around existing application blocks, although again you can easily create your own. While the number of handlers and the details on how they will work are not entirely set in concrete, here is what we are hoping to include:
We're very excited by the potential for this block to help simplify your code and provide increased flexibility to change cross-cutting concerns at different stages of the application lifecycle. Keep in mind that the first drop of the Policy Injection Application Block (in the February 2007 CTP) will still be incomplete, but we'd love to hear your feedback to help us make the final release as valuable as possible.
By the way, if you're not the kind of person who likes surprises, apologies for springing this on you so late. It wasn't our intention to be secretive, however until very recently we were still not sure if we were going to be able to include this functionality in this release of Enterprise Library, so we didn't want to set expectations too early. Hopefully it was worth the wait, and that you can file it under "good surprises" :-)
Thanks to Alex Homer for the great graphics, which were taken from the draft documentation.
PingBack from http://blogs.msdn.com/edjez/archive/2007/02/23/policy-injection-app-block-behind-the-scenes.aspx
Very cool indeed. Is this all config file driven or are there any attributes to support this functionality a la AOP (Aspect Oriented Prog)
Kris: so far it is all configuration driven, although one of the matching rules will check for the existence of a particular attribute, so you can do something like this:
[Tag("AuthorizeMe")]
public void DoStuff()
... where there is a policy defined in configuration that will look for this particular tag.
For the final release we're hoping to add the ability to explicitly attach handlers to types and methods via attributes, without the need for any configuration.
Tom
Hi Tom,
I am wondering if (or how) the ObjectBuilder is used in this Policy Injection Application Block?
Thanks
Do you wonder how to apply authorization, validation, logging and other requierements to you business
Kevin - the PIAB uses Object Builder in much the same way as the other blocks, for example by configuring the core components by injecting the configuration data.
This block is going to be very useful. Thanks for your efforts. Any study on performance impact on execution. I have also started a kind of application block called Web Analytics. Its hosted on CodePlex. Pls let me know your feedback.
http://dotnetwithme.blogspot.com/2007/02/started-my-first-codeplex-project.html
Vikas Goyal
Many software projects experience disappointing productivity. Often productivity problems are inherent
Great to see this implemented!
As far as the factory for instance creation is concerned, does this place any restrictions on how instances can be instantiated e.g. only via a default constructor, thus no parameterised constructors?
Cheers,
Matt
Matt - take a look at Ed's post for some more details on how the interception mechanism works and how you can replace it with a different mechanism. But with our default remoting proxy mechansim, the main restrictions are that you must create the object with our proxy rather than "new", and the object must either derive from MarshalByRefObject or have an explicit interface for marshalling. I don't believe there are any restrictions on the use of parameters in the constructor.
Why not just go all the way and build an AOP framework which are target towards cross-cutting concerns? It's really what it is, or part of AOP anyway but with a Microsoft name tagged on it (Policy instead of Aspects).
Also, have you tried this with WCF? WCF doesn't really like proxys.