2017-09-24 7 views
2

Je voudrais obtenir le comportement décrit dans la réponse here mais en utilisant la configuration par le code. L'exemple de code montre l'attribut personnalisé en cours de création sans rien lié à l'unité et en ajoutant le comportement via la configuration.Interception d'un .NET utilisant des attributs personnalisés

L'attribut personnalisé est dans l'assembly séparé référencé dans la même solution.

Le problème est que jeter une exception lors de la configuration:

InvalidOperationException: Le type Microsoft.Practices.Unity.InterceptionExtension.CustomAttributeMatchingRule ne dispose pas d'un constructeur qui prend les paramètres (LogAttribute, Boolean).

container 
    .AddNewExtension<Interception>() 
    .Configure<Interception>() 
     .AddPolicy("MyLoggingPolicy") 
     .AddMatchingRule<CustomAttributeMatchingRule>(
     new InjectionConstructor(typeof(Abstractions.Attributes.LogAttribute), true)) 
     .AddCallHandler<LoggingHandler>(new ContainerControlledLifetimeManager()) 
      .Interception 
      .Container 
     .RegisterType<IFirstInterface>(new InjectionFactory((context) => FirstClassFactoryMethod())) 
     .RegisterType<ISecondInterface>(new InjectionFactory((context) => SecondClassFactoryMethod())); 

[AttributeUsage(AttributeTargets.Method)] 
public class LogAttribute : Attribute { } 

public class LoggingHandler : ICallHandler 
{ 
    public int Order { get; set; } 

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) 
    { 
     Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")} Started: {input.MethodBase.Name}"); 
     var result = getNext()(input, getNext); 
     Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")} Completed: {input.MethodBase.Name}"); 
     return result; 
    } 
} 

Mise à jour de la ligne qui jette à:

.AddMatchingRule(
    new CustomAttributeMatchingRule(typeof(Abstractions.Attributes.LogAttribute), true)) 

empêche l'exception d'être jetée, mais le LoggingHandler ne reçoit pas d'appels des méthodes qui ont l'attribut [Log].

REMARQUE: Les méthodes marquées avec [Log] sont des méthodes publiques, dans un assembly différent, dans les classes qui sont instanciées à l'aide de .Resolve().

+0

Est-il possible que les méthodes que vous interceptent ne sont pas virtuelles ou non partie d'une définition d'interface, ou vous les résolvez en tant que types concrets pas interfaces? Parce que cela empêchera l'interception –

+0

@vasiloreshenski Cela fait partie de la définition de l'interface. Et je le résous comme montré ci-dessus: .RegisterType (nouvelle InjectionFactory ((context) => FirstClassFactoryMethod())). Est-ce que ça doit encore être virtuel? – Filip

Répondre

3

Pour toute personne qui rencontre le même problème - je devais définir le comportement d'interception sur les types enregistrés:

.RegisterType<IFirstInterface>(
    new InjectionFactory((context) => FirstClassFactoryMethod()) 
    new Interceptor<TransparentProxyInterceptor>() 
    new InterceptionBehavior<PolicyInjectionBehavior>()) 
.RegisterType<ISecondInterface>(
    new InjectionFactory((context) => SecondClassFactoryMethod()) 
    new Interceptor<TransparentProxyInterceptor>() 
    new InterceptionBehavior<PolicyInjectionBehavior>()));