The streamlined InterceptionExtension.PolicyDefinition APIs provide a simplified way to wire up RuleDriven policies and their IMatchingRules and ICallHandlers. The general purpose APIs require repeated calls to the InjectedMembers.ConfigureInjectionFor and RegisterType methods. The streamlined extension APIs reduce the overhead required to manage the various strings, cross links, thus making the process more obvious and convenient.
Everything you can do with the InterceptionExtension.PolicyDefinition API can be done with the general-purpose APIs.
For more information about interception, see Using Interception with Unity.
For more information about selecting the objects and their members to add a handler pipeline, see Configuring and Using Matching Rules.
The following are streamlined configuration InterceptionExtension.PolicyDefinition methods:
- AddPolicy. These methods are a set of methods on the interception type.
- AddMatchingRule. These methods are on the PolicyDefinition class you get when you call AddPolicy.
- AddCallHandler. These methods are on the PolicyDefinition class you get when you call AddPolicy.
These methods are only used for configuring rule driven policies, which are also the only policies configurable with the standard installation and setup. For user-defined policies, you must use the general purpose APIs.
The streamlined InterceptionExtension.PolicyDefinition API is similar to the expanded RegisterType API in that you can provide a lifetime manager (just like RegisterType), the mapping, and the injection configuration. It also differs in the following ways:
- The entry point for the API is the AddPolicy method in the Interception extension.
- The result of this method is a transient PolicyDefinition object, which can be used to AddMatchingRules and AddCallHandlers. These methods add rules and handlers to the policy, but they also configure the container as necessary.
- The signatures for these methods are similar to those of RegisterType, but the names imply the interface being registered instead of relying on generic type parameters, as with the general-purpose RegisterTypeMethods. The following is an example.
Instead of
RegisterType<ICallHandler, MyCallHandler>(...)
you use
AddCallHandler<MyCallHandler>(...).
There are three approaches for using the streamlined interception methods:
- Supply a string parameter. Use a string parameter to indicate that you want to use an object that was configured elsewhere. If you used the general purpose API to configure a handler in the container, you would just "link" to it with this approach.
Note: |
|---|
| You can supply a string and configure the corresponding rule or handler at a later time. |
public void APolicyExternallyConfiguredRulesAndHandlers()
{
IUnityContainer container = new UnityContainer();
container.AddNewExtension<Interception>();
container
.Configure<Interception>()
.AddPolicy("Foot")
.AddMatchingRule("rule1")
.AddCallHandler("handler1")
.AddCallHandler("handler2").Interception.Container
.RegisterType<IMatchingRule, AlwaysMatchingRule>("rule1")
.RegisterType<ICallHandler,LogCallHandler>(
"handler1",
new InjectionConstructor("handler1"))
.RegisterType<ICallHandler,LogCallHandler>(
"handler2",
new InjectionConstructor("handler2"),
new InjectionProperty("Order", 10));
LogCallHandler.Calls.Clear();
container
.Configure<Interception>()
.SetInjectorFor<TypeToIntercept>("wrappable", new TransparentProxyPolicyInjector());
TypeToIntercept wrappable1 = container.Resolve<TypeToIntercept>("wrappable");
wrappable1.Method2();
}
- Supply an instance. Use this case when you already have the object and want only the new policy to use it.
public void APolicyGivenRulesAndHandlers()
{
IUnityContainer container = new UnityContainer();
container.AddNewExtension<Interception>();
IMatchingRule rule1 = new AlwaysMatchingRule();
ICallHandler handler1 = new CallCountHandler();
container
.Configure<Interception>()
.AddPolicy("Foot")
.AddMatchingRule(rule1)
.AddCallHandler(handler1);
container
.Configure<Interception>()
.SetInjectorFor<TypeToIntercept>("wrappable", new TransparentProxyPolicyInjector());
TypeToIntercept wrappable1 = container.Resolve<TypeToIntercept>("wrappable");
wrappable1.Method2();
}
- Supply a type. Supply a type either as a generic type parameter or a normal parameter, and, optionally, a name, a lifetime container, and injection configuration in any combination. Use this case when you need to configure the container for the creation of a new object. If you do not specifiy a name, one is created. If a policy with the specified name exists, it will be overwritten. In this approach, you describe how to resolve for injection.
public void APolicyGivenRulesAndHandlersTypes()
{
IUnityContainer container = new UnityContainer();
container.AddNewExtension<Interception>();
container
.Configure<Interception>()
.AddPolicy("Foot")
.AddMatchingRule(typeof(AlwaysMatchingRule))
.AddCallHandler(typeof(LogCallHandler));
LogCallHandler.Calls.Clear();
container
.Configure<Interception>()
.SetInjectorFor<TypeToIntercept>("wrappable", new TransparentProxyPolicyInjector());
TypeToIntercept wrappable1 = container.Resolve<TypeToIntercept>("wrappable");
wrappable1.Method2();
}
One significant difference between the RegisterType methods and this streamlined API is that when you do not specify a name, a name is generated for you, so all "anonymous" definitions without names will not be overwritten by other definitions without names. If you do specify a name, it is used and may override previous existing policies with the same name.
You can use generic parameter support when you configure for injection, just like you do with RegisterType or ConfigureInjection.
The generic versions of the AddMatchingRule and AddCallHandler methods contain the types you can supply, unlike RegisterType. RegisterType is a general purpose method and has no constraints on the types you can supply. For AddCallHandler<TCallHandler>(), you can only provide a type value for TCallHandler that implements ICallHandler. The non-generic version of the method is limited to performing run-time checks.