unitycontainer unity registertype ioc injection dependency container c# .net unity-container unity-interception

c# - registertype - Use Unity para interceptar todas las llamadas a IMyInterface.SomeMethod



unity container lifetime (3)

Estoy tratando de aprender Unity Interceptors y estoy teniendo un duro trabajo.

Digamos que tengo una interfaz como esta:

public interface IMyInterface { void SomeMethod(); }

Y tengo un número desconocido de clases que implementan esa interfaz como esta:

public class SpecificClass1 : IMyInterface { public void SomeMethod() { Console.WriteLine("Method Called"); } }

Estoy buscando una manera de decir, "para todas las instancias de IMyInterface (no quiero enumerarlas), cuando se llama a SomeMethod ejecutar mi interceptor.

Es la no enumeración de la clasificación que me está dando problemas. (Hay muchos ejemplos si puedes enumerar todas tus clases).

He leído acerca de la intercepción de tipo, pero parece que no puedo encontrar si hará lo que estoy buscando.

¿Algún experto en Unity sabe cómo hacer lo que estoy buscando?


@GSerjo, ha descrito el enfoque de intercepción de Unity que funciona bien. Si desea automatizar la configuración de la intercepción, puede utilizar la extensión UnityContainer para conectar automáticamente toda la intercepción de la interfaz y los comportamientos. Si quisiera entrar en una intercepción más específica (nombres de métodos, firmas, valores de retorno, etc.) entonces probablemente necesitaría ver Inyección de políticas (usando reglas de concordancia con CallHandlers).

Entonces, en este caso, la extensión del contenedor sería:

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); } ); } } }

Entonces podrías usarlo así:

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();

Ahora, cuando se registra la interfaz, las políticas de intercepción apropiadas también se agregarán al contenedor. Entonces, en este caso, si la interfaz registrada es de tipo IMyInterface o IMyOtherInterface, las políticas se configurarán para la intercepción de la interfaz y también se agregarán los Comportamientos de intercepción MyInterceptionBehavior y AnotherInterceptionBehavior.

Tenga en cuenta que Unity 3 (publicado después de esta pregunta / respuesta) agregó una función de Registro por Convención que puede hacer lo que hace esta extensión (sin tener que escribir ningún código personalizado). Un ejemplo de la Guía del desarrollador para la inyección de dependencias usando la unidad :

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>() });


La configuración de la intercepción requiere múltiples acciones incl. Configuración de tipos interceptados, políticas y manejadores.

Primero consulte Uso de la intercepción en aplicaciones para obtener detalles generales sobre los tipos de situaciones en las que se admite la intercepción (con o sin un contenedor DI, por ejemplo). Luego, consulte la Intercepción de tipo para obtener más detalles sobre los interceptores de tipo compatibles. Especialmente tome nota de qué interceptores pueden usarse con el tipo de su clase (de lo contrario, los manejadores nunca se activarán).

Cuando haya decidido qué interceptor usar, configúrelo y cree un manejador de llamadas suficiente según los enlaces anteriores. Si aún tiene problemas en este punto, publique una pregunta más detallada. Si ya lo ha hecho, publique las configuraciones y el código como "no enumeración de la clasificación", simplemente no da ninguna pista de lo que realmente está preguntando. ¿Por casualidad quiere decir con "enumeración" que asigna una política basada en atributos y no puede lograr lo que quiere sin ella?


Podría crear InterceptionBehavior luego registrarlo en una clase específica. Tenga en cuenta que puede filtrar los métodos de ejecución en Invoke través de la IMethodInvocation input

using System; using System.Collections.Generic; using System.Linq; using Microsoft.Practices.Unity; using Microsoft.Practices.Unity.InterceptionExtension; using NUnit.Framework; namespace UnitTests { [TestFixture] public class ForTest { [Test] public void Test() { IUnityContainer container = new UnityContainer().AddNewExtension<Interception>(); container.RegisterType<IMyInterface, SpecificClass1>( new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<MyInterceptionBehavior>()); var myInterface = container.Resolve<IMyInterface>(); myInterface.SomeMethod(); } } public interface IMyInterface { void SomeMethod(); } public class SpecificClass1 : IMyInterface { #region IMyInterface public void SomeMethod() { Console.WriteLine("Method Called"); } #endregion } public class MyInterceptionBehavior : IInterceptionBehavior { public bool WillExecute { get { return true; } } #region IInterceptionBehavior public IEnumerable<Type> GetRequiredInterfaces() { return Enumerable.Empty<Type>(); } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { IMethodReturn result = getNext()(input, getNext); Console.WriteLine("Interception Called"); return result; } #endregion } }

Salida de consola

Method Called Interception Called

Más sobre la intercepción con la unidad