2011-06-17 10 views
13

¿Cómo puedo obtener Ninject.Extensions.Interception dejar que básicamente me ato un interceptor específica a cualquier método que tiene un atributo ... psudocode:Ninject Interceptar cualquier método con cierto atributo?

Kernel.Intercept(context => context.Binding.HasAttribute<TransactionAttribute>()) 
     .With<TransactionInterceptor> 

Con una clase como:

public SomeClass 
{ 
    [TransactionAttribute] 
    public void SomeTransactedMethod() 
    { /*do stuff */ } 
} 

Respuesta

13

suponiendo que está utilizando Ninject.Extensions.Interception esto debe hacer el truco

public class TransactionInterceptor : IInterceptor 
{ 
    public void Intercept(IInvocation invocation) 
    { 
     // Do something... 
    } 
} 

public class TransactionAttribute : InterceptAttribute 
{ 
    public override IInterceptor CreateInterceptor(IProxyRequest request) 
    { 
     return new TransactionInterceptor(); 
    } 
} 

public class SomeClass 
{ 
    [Transaction] 
    public virtual void SomeTransactedMethod() { } 
} 

Asegúrese de que el método que debe ser interceptada es marca ed como virtual.

Cuando se llama SomeTransactedMethod(), debe ser interceptado.

var kernel = new StandardKernel(); 
kernel.Bind<SomeClass>().ToSelf(); 

var someClass = kernel.Get<SomeClass>(); 
someClass.SomeTransactedMethod(); 

ACTUALIZACIÓN

Se puede crear una estrategia de planificación personalizada.

public class CustomPlanningStrategy<TAttribute, TInterceptor> : 
    NinjectComponent, IPlanningStrategy 
     where TAttribute : Attribute 
     where TInterceptor : IInterceptor 
{ 
    private readonly IAdviceFactory adviceFactory; 
    private readonly IAdviceRegistry adviceRegistry; 

    public CustomPlanningStrategy(
     IAdviceFactory adviceFactory, IAdviceRegistry adviceRegistry) 
     { 
      this.adviceFactory = adviceFactory; 
      this.adviceRegistry = adviceRegistry; 
     } 

     public void Execute(IPlan plan) 
     { 
      var methods = GetCandidateMethods(plan.Type); 
      foreach (var method in methods) 
      { 
       var attributes = method.GetCustomAttributes(
        typeof(TAttribute), true) as TAttribute[]; 
       if (attributes.Length == 0) 
       { 
        continue; 
       } 

       var advice = adviceFactory.Create(method); 

       advice.Callback = request => request.Kernel.Get<TInterceptor>(); 
       adviceRegistry.Register(advice); 

       if (!plan.Has<ProxyDirective>()) 
       { 
        plan.Add(new ProxyDirective()); 
       } 
      } 
     } 
    } 

    private static IEnumerable<MethodInfo> GetCandidateMethods(Type type) 
    { 
     var methods = type.GetMethods(
      BindingFlags.Public | 
      BindingFlags.NonPublic | 
      BindingFlags.Instance 
     ); 

     return methods.Where(ShouldIntercept); 
    } 

    private static bool ShouldIntercept(MethodInfo methodInfo) 
    { 
     return methodInfo.DeclaringType != typeof(object) && 
       !methodInfo.IsPrivate && 
       !methodInfo.IsFinal; 
    } 
} 

Esto debería funcionar ahora.

var kernel = new StandardKernel(); 
kernel.Components.Add<IPlanningStrategy, 
    CustomPlanningStrategy<TransactionAttribute, TransactionInterceptor>>(); 

kernel.Bind<SomeClass>().ToSelf(); 

var someClass = kernel.Get<SomeClass>(); 
someClass.SomeTransactedMethod(); 
+0

puedo tener mis atributos que heredan de InterceptAttribute , como el dominio donde la transacción ion attribute se define sin conocimiento de las preocupaciones DI ... Por eso tengo que hacerlo a través del método Kernel.Intercept, que se define dentro de la capa de la aplicación. – somemvcperson

+0

Ok, ahora veo ... He realizado una implementación cruda de IPlanningStrategy que con suerte servirá para solucionar el problema. Es posible que desee consultar el código real de [Ninject.Extensions.Inteception] (https://github.com/ninject/ninject.extensions.interception) en Github para conocer formas de mejorar la estrategia de planificación personalizada. – mrydengren

+0

Hmm parece un poco más trabajo que lo que buscaba ... Estaba seguro de que hace un tiempo vi un ejemplo de un solo trazador de líneas simple usando el método de extensión Intercept en Kernel, le daré otra búsqueda en internet y si todo más falla, prueba lo de arriba ... gracias. – somemvcperson

2

Este es el código que se utiliza para el mismo propósito

//Code in Bind Module 
this.Bind(typeof(ServiceBase<,>)) 
    .ToSelf() 
    .InRequestScope() 
    .Intercept() 
    .With<TransactionInterceptor>(); 

Y

public class TransactionInterceptor : IInterceptor 
{ 
    #region Constants and Fields 

    public ISession session; 
    private ISessionFactory sessionFactory; 

    #endregion 

    #region Constructors and Destructors 

    public TransactionInterceptor(ISession session, ISessionFactory sessionFactory) 
    { 
     this.sessionFactory = sessionFactory; 
     this.session = session; 
    } 


    #endregion 

    public void Intercept(IInvocation invocation) 
    { 
     try 
     { 
      if (!session.IsConnected) 
       session = sessionFactory.OpenSession(); 

      session.BeginTransaction(); 
      invocation.Proceed(); 
      if (this.session == null) 
      { 
       return; 
      } 

      if (!this.session.Transaction.IsActive) 
      { 
       return; 
      } 
      else 
      { 
       this.session.Transaction.Commit(); 
      } 
     } 
     catch (Exception) 
     { 
      if (this.session == null) 
      { 
       return; 
      } 

      if (!this.session.Transaction.IsActive) 
      { 
       return; 
      } 

      this.session.Transaction.Rollback(); 

      throw; 
     } 
    } 
} 

Y código para TransactionAttribute

public class TransactionAttribute : InterceptAttribute 
{ 
    #region Public Methods 

    public override IInterceptor CreateInterceptor(IProxyRequest request) 
    { 
     return request.Context.Kernel.Get<TransactionInterceptor>() ; 
    } 

    #endregion 
} 
Cuestiones relacionadas