@GSerjo, ha delineato l'approccio intercettazione unità che funziona bene. Se si desidera automatizzare la configurazione dell'intercettazione, è possibile utilizzare UnityContainerExtension per collegare automaticamente tutta l'intercettazione dell'interfaccia e i comportamenti. Se si desidera accedere a un'intercettazione più specifica (nomi di metodi, firme, valori di ritorno, ecc.), Sarà probabilmente necessario consultare Policy Injection (utilizzando le regole di corrispondenza con CallHandlers).
Quindi, in questo caso l'estensione del contenitore sarà simile:
public class UnityInterfaceInterceptionRegisterer : UnityContainerExtension
{
private List<Type> interfaces = new List<Type>();
private List<IInterceptionBehavior> behaviors =
new List<IInterceptionBehavior>();
public UnityInterfaceInterceptionRegisterer(Type interfaceType,
IInterceptionBehavior interceptionBehavior)
{
interfaces.Add(interfaceType);
behaviors.Add(interceptionBehavior);
}
public UnityInterfaceInterceptionRegisterer(Type[] interfaces,
IInterceptionBehavior[] interceptionBehaviors)
{
this.interfaces.AddRange(interfaces);
this.behaviors.AddRange(interceptionBehaviors);
ValidateInterfaces(this.interfaces);
}
protected override void Initialize()
{
base.Container.AddNewExtension<Interception>();
base.Context.Registering +=
new EventHandler<RegisterEventArgs>(this.OnRegister);
}
private void ValidateInterfaces(List<Type> interfaces)
{
interfaces.ForEach((i) =>
{
if (!i.IsInterface)
throw new ArgumentException("Only interface types may be configured for interface interceptors");
}
);
}
private bool ShouldIntercept(RegisterEventArgs e)
{
return e != null && e.TypeFrom != null &&
e.TypeFrom.IsInterface && interfaces.Contains(e.TypeFrom);
}
private void OnRegister(object sender, RegisterEventArgs e)
{
if (ShouldIntercept(e))
{
IUnityContainer container = sender as IUnityContainer;
var i = new Interceptor<InterfaceInterceptor>();
i.AddPolicies(e.TypeFrom, e.TypeTo, e.Name, Context.Policies);
behaviors.ForEach((b) =>
{
var ib = new InterceptionBehavior(b);
ib.AddPolicies(e.TypeFrom, e.TypeTo, e.Name, Context.Policies);
}
);
}
}
}
allora si potrebbe utilizzare in questo modo:
IUnityContainer container = new UnityContainer()
.AddExtension(new UnityInterfaceInterceptionRegisterer(
new Type[] { typeof(IMyInterface),
typeof(IMyOtherInterface) },
new IInterceptionBehavior[] { new MyInterceptionBehavior(),
new AnotherInterceptionBehavior() }
));
container.RegisterType<IMyInterface, SpecificClass1>();
var myInterface = container.Resolve<IMyInterface>();
myInterface.SomeMethod();
Ora, quando l'interfaccia è iscritto le politiche di intercettazione appropriate saranno anche aggiunto al contenitore. In questo caso, se l'interfaccia registrata è di tipo IMyInterface o IMyOtherInterface, verranno quindi impostate le policy per l'intercettazione dell'interfaccia e verranno aggiunti anche i comportamenti di intercettazione MyInterceptionBehavior e AnotherInterceptionBehavior.
Nota che Unity 3 (rilasciato dopo questa domanda/risposta) ha aggiunto una funzione Registration by Convention che può fare ciò che fa questa estensione (senza dover scrivere alcun codice personalizzato). Un esempio da Developer's Guide to Dependency Injection Using Unity:
var container = new UnityContainer();
container.AddNewExtension<Interception>();
container.RegisterTypes(
AllClasses.FromLoadedAssemblies().Where(
t => t.Namespace == "OtherUnitySamples"),
WithMappings.MatchingInterface,
getInjectionMembers: t => new InjectionMember[]
{
new Interceptor<VirtualMethodInterceptor>(),
new InterceptionBehavior<LoggingInterceptionBehavior>()
});