2016-04-29 43 views
1

我想用裝飾器包裝我的通用接口,但它根本不起作用,在我看來,從其他問題來看,做到這一點的唯一方法是通過明確地爲每個裝飾器進行操作,我的問題是關於是否有可能在ninject中包裝實現與特定Decorater的某個接口的所有類型。使用ninject的通用裝飾模式

代碼:

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

回答

0

我發現其中的伎倆此擴展方法:

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

如果您需要裝飾呼籲在實現接口的所有類的一些方法,你可以嘗試代理所有的綁定。

Ninject有一個名爲 - Interception的擴展名,它允許你截取對你的方法的特定調用,並用一些邏輯來包裝它。

Here是一個很好的文章。

希望它有幫助。

+0

我需要能夠得到一個調用操作的結果,這可能是某種通用的類型結果攔截似乎不提供的? – Xerxes