2013-07-01 2 views
1

인수 이름에 의존하지 않고 생성자 매개 변수로 인스턴스를 만드는 ninject 팩터 리를 어떻게 사용할 수 있습니까?ninject 팩토리 생성자 또는 런타임 generics로 선택

일반 정의에 바인딩하기 때문에 문제는 ToConstructor() -Method가 작동하지 않는다는 것입니다.

다음 예제는 해당 생성자 인수 이름과 함께 factory 메소드를 사용할 경우 작동하지만 이름에 의존하는 것이 싫습니다.

누군가가 잘못된 이름을 선택하거나 파생 클래스에서 ctor- 인수의 이름을 바꾸면 다음 솔루션은 매우 취약하고 깨집니다.

모든 솔루션?

다음은 예제 코드입니다 :

[TestFixture] 
public class NinjectFactoryBindingsTest 
{ 
    [Test] 
    public void ConstructorSelectionWithArguments() 
    { 
     NinjectSettings ninjectSettings = new NinjectSettings(); 
     ninjectSettings.LoadExtensions = false; 

     using (var kernel = new StandardKernel(ninjectSettings, new FuncModule())) 
     { 
      // IDependencyA will be passed to the factory, therefore it is not bounded 
      //kernel.Bind<IDependencyA>().To<DependencyA>(); 
      kernel.Bind<IDependencyB>().To<DependencyB>(); 

      kernel.Bind(typeof(IGenericBaseClass<>)).To(typeof(GenericDerivedClass<>)); 
      kernel.Bind<IGenericClassFactory>().ToFactory(); 

      IGenericClassFactory factory = kernel.Get<IGenericClassFactory>(); 

      DependencyA dependencyA = new DependencyA(); 

      IGenericBaseClass<GenericImpl> shouldWorkInstance = factory.Create<GenericImpl>(dependencyA); 

      Assert.NotNull(shouldWorkInstance); 

     } 
    } 
}  

public interface IGenericClassFactory 
{ 
    IGenericBaseClass<TGeneric> Create<TGeneric>(IDependencyA someName) where TGeneric : IGeneric; 
    // This works, but relies on ctor-param-names!!! 
    // IGenericBaseClass<TGeneric> Create<TGeneric>(IDependencyA otherNameThanInBaseClass) where TGeneric : IGeneric; 
} 

public class DependencyA : IDependencyA 
{ 
} 

public class DependencyB : IDependencyB 
{ 
} 

public class GenericDerivedClass<TGeneric> : GenericBaseClass<TGeneric> where TGeneric : IGeneric 
{ 
    public GenericDerivedClass(IDependencyA otherNameThanInBaseClass, IDependencyB dependencyB) 
     : base(otherNameThanInBaseClass, dependencyB) 
    { 
    } 
} 

public abstract class GenericBaseClass<TGeneric> : IGenericBaseClass<TGeneric> where TGeneric : IGeneric 
{ 
    protected GenericBaseClass(IDependencyA dependencyA, IDependencyB dependencyB) 
    { 
    } 
} 

public interface IGenericBaseClass<TGeneric> where TGeneric : IGeneric 
{ 
} 

public interface IDependencyB 
{ 
} 

public interface IDependencyA 
{ 
} 

public class GenericImpl : IGeneric 
{ 
} 

public interface IGeneric 
{ 
} 

답변

1

공장 확장 인수가 전달 될 생성자 인수와 같은 이름을 가지고 있어야합니다 규칙을 가지고있다. 다르게 할 수있는 쉬운 방법은 없습니다. 내가 생각할 수있는 유일한 방법은 다음에 관한 것입니다.

  1. IDependencyA에 대한 참조를 보유 할 수있는 새로운 IParameter 구현을 만듭니다. 이 가져 오기 <> 요청
  2. 에 전달 있도록 IParameter 구현의 인스턴스를 생성
  3. 하드 코드 공장 또는 사용자 정의 IInstanceProvider (설명서 참조) 중 하나를 만들기 IDependencyA에 대한 새 바인딩을 추가 : Bind<IDependency>().ToMethod(ctx => extract and return your parameter from the context)
+0

Thx Remo 아이디어입니다. 나는'IConstructorArgument'를 구현하는 새로운 Parameter를 만들었습니다. 이제'bool AppliesToTarget (...) '으로 확인하는 것이 쉽습니다. – crip

관련 문제