2016-04-29 12 views
1

Ich versuche, meine generische Schnittstellen mit einem Dekorator zu umwickeln, aber es funktioniert einfach nicht, es scheint mir von den anderen Fragen, dass der einzige Weg dies zu tun ist, indem es explizit für jeden Dekorateur tut, Meine Frage ist, ob es möglich ist, alle Typen, die eine bestimmte Schnittstelle mit einem bestimmten Decorator in Ninject implementieren, zu umbrechen.Generic Decorator Muster mit ninject

Code:

static void BindMediatr(IKernel kernel) { 
    kernel.Components.Add < IBindingResolver, ContravariantBindingResolver >(); 

    kernel.Bind(scan => scan.FromAssemblyContaining <IMediator>() 
    .SelectAllClasses() 
    .BindDefaultInterface()); 

    kernel.Bind <SingleInstanceFactory>().ToMethod(ctx => t => ctx.Kernel.Get(t)); 
    kernel.Bind <MultiInstanceFactory>().ToMethod(ctx => t => ctx.Kernel.GetAll(t)); 
    kernel.Bind(
    x => x.FromThisAssembly() 
    .SelectAllClasses() 
    .InheritedFromAny(typeof(IAsyncRequestHandler < , >)) 
    .BindAllInterfaces()); 

    kernel.Bind(typeof(IAsyncRequestHandler < , >)) 
    .To(typeof(Decorater < , >)) 
    .WhenInjectedInto <ApiController>(); 
} 

public class Decorater < TRequest, TResponse > 
    : IAsyncRequestHandler < TRequest, TResponse > 
    where TRequest: IAsyncRequest <TResponse> { 
    IAsyncRequestHandler < TRequest, 
    TResponse > _decoratee; 

    public Decorater(IAsyncRequestHandler < TRequest, TResponse > decoratee) { 
    _decoratee = decoratee; 
    } 

    public Task <TResponse> Handle(TRequest message) { 
    // do something here 
    } 
    } 

Antwort

0

fand ich diese Erweiterung Methode, die funktioniert der Trick:

public static class KernelExtensions 
    { 
     /// <summary> 
     /// Binds an open generic type to its implementation and adds all its defined decorators 
     /// </summary> 
     /// <param name="kernel">Ninject Container</param> 
     /// <param name="openGenericType">Open generic Type</param> 
     /// <param name="assembly">Assembly to scan for the open generic type implementation</param> 
     /// <param name="decoratorTypes">Types of the decorators. Order matters. Order is from the most outer decorator to the inner decorator</param> 
     public static void BindManyOpenGenericsWithDecorators(this IKernel kernel, Type openGenericType, Assembly assembly, params Type[] decoratorTypes) 
     { 
      var allImplementations = GetAllTypesImplementingOpenGenericType(openGenericType, assembly); 

      foreach (var type in allImplementations.Where(type => !decoratorTypes.Contains(type))) 
      { 
       var genericInterface = type.GetInterfaces().FirstOrDefault(x => openGenericType.IsAssignableFrom(x.GetGenericTypeDefinition())); 

       // real implementation 
       var parentType = decoratorTypes.Last(); 
       kernel.Bind(genericInterface).To(type) 
       .WhenInjectedInto(parentType); 
      } 

      for (var i = 0; i <= decoratorTypes.Count() - 1; i++) 
      { 
       var decoratorType = decoratorTypes[i]; 

       if (i == 0) 
       { 
        // most outer decorator 
        kernel.Bind(openGenericType).To(decoratorType); 
       } 
       else 
       { 
        // inner decorators 
        var parentType = decoratorTypes[i - 1]; 
        kernel.Bind(openGenericType).To(decoratorType) 
         .WhenInjectedInto(parentType); 
       } 
      } 
     } 

     private static IEnumerable<Type> GetAllTypesImplementingOpenGenericType(Type openGenericType, Assembly assembly) 
     { 
      return (from type in assembly.GetTypes() 
        from interfaceType in type.GetInterfaces() 
        let baseType = type.BaseType 
        where 
        (baseType != null && baseType.IsGenericType && 
        openGenericType.IsAssignableFrom(baseType.GetGenericTypeDefinition())) || 
        (interfaceType.IsGenericType && 
        openGenericType.IsAssignableFrom(interfaceType.GetGenericTypeDefinition())) 
        select type); 
     } 
    } 
0

Wenn Sie den Anruf für ein bestimmtes Verfahren in allen Klassen dekorieren, die die Schnittstelle zu realisieren, können Sie alle Ihre Bindungen zu Proxy versuchen.

Ninject hat eine Erweiterung mit dem Namen - Interception, mit der Sie die Methode mit dem bestimmten Aufruf für Sie abfangen und mit einer gewissen Logik umbrechen können.

Here ist ein guter Artikel darüber.

Hoffe, es hilft.

+0

ich die Ergebnisse einer Invoke Aktion in der Lage sein müssen, zu erhalten, die von einem bestimmten Ergebnis sein könnte generischer Typ die Interception scheint nicht zu bieten ? – Xerxes