2011-01-29 11 views
21

Autofac automatycznie generuje fabryki dla Func<T>; Mogę nawet przekazać parametry.Czy Ninject obsługuje Func (fabryka generowana automatycznie)?

public class MyClass 
{ 
    public MyClass(Func<A> a, Func<int, B> b) 
    { 
     var _a = a(); 
     var _b = b(1); 
    } 
} 

Czy mogę zrobić to samo z Ninject? Jeśli nie, jakie obejście można zastosować?

Dzięki.

Aktualizacja:

Wystarczy znaleźć ten post, wydaje się, że odpowiedź brzmi nie:

How do I handle classes with static methods with Ninject?

Odpowiedz

29

NB Ninject 3.0 i później ma to w pełni obsługiwany przy użyciu pakietu Ninject.Extensions.Factory, zobacz wiki: - https://github.com/ninject/ninject.extensions.factory/wiki


EDYCJA: UWAGA: Bind<T>().ToFactory() implementacja w wersji 2.3 (która nie jest w pełni przetestowanym obsługiwanym wydaniem, ale is available from the CodeBetter server)

Ninject obecnie nie obsługuje tego natywnie. Planowaliśmy dodać to do następnej wersji. Jednak wsparcie można łatwo dodać, konfigurując odpowiednie powiązanie. Po prostu załaduj moduł poniżej i ciesz się.

public class FuncModule : NinjectModule 
{ 
    public override void Load() 
    { 
     this.Kernel.Bind(typeof(Func<>)).ToMethod(CreateFunc).When(VerifyFactoryFunction); 
    } 

    private static bool VerifyFactoryFunction(IRequest request) 
    { 
     var genericArguments = request.Service.GetGenericArguments(); 
     if (genericArguments.Count() != 1) 
     { 
      return false; 
     } 

     var instanceType = genericArguments.Single(); 
     return request.ParentContext.Kernel.CanResolve(new Request(genericArguments[0], null, new IParameter[0], null, false, true)) || 
       TypeIsSelfBindable(instanceType); 
    } 

    private static object CreateFunc(IContext ctx) 
    { 
     var functionFactoryType = typeof(FunctionFactory<>).MakeGenericType(ctx.GenericArguments); 
     var ctor = functionFactoryType.GetConstructors().Single(); 
     var functionFactory = ctor.Invoke(new object[] { ctx.Kernel }); 
     return functionFactoryType.GetMethod("Create").Invoke(functionFactory, new object[0]); 
    } 

    private static bool TypeIsSelfBindable(Type service) 
    { 
     return !service.IsInterface 
       && !service.IsAbstract 
       && !service.IsValueType 
       && service != typeof(string) 
       && !service.ContainsGenericParameters; 
    } 

    public class FunctionFactory<T> 
    { 
     private readonly IKernel kernel; 

     public FunctionFactory(IKernel kernel) 
     { 
      this.kernel = kernel; 
     } 

     public Func<T> Create() 
     { 
      return() => this.kernel.Get<T>(); 
     } 
    } 
} 
+0

Dzięki za kod! Z niecierpliwością czekam na kolejną wersję. –

+0

Dzięki za całą ciężką pracę Remo. Czy możliwe jest rozszerzenie kodu do pracy z Func >? – Anders

+0

Pewnie, że tak. Zmień metodę FunctionFactory.Create, sprawdź wartość IEnumerable i zwróć wartość GetAll. –