2015-01-06 3 views
2

나는 두 바인딩이 : 기본적 아이디어는 내가 (처음 바인딩에 정의) 공유 캐시를 가지고 있지만 것입니다수동으로 해결 종속성

Bind<ICache>().ToMethod(ctx => FactoryMethods.CreateCache(
     ctx.Kernel.Get<IXXX>(), 
     ctx.Kernel.Get<IYYY>())) 
    .WhenTargetHas<SharedCacheAttribute>() 
    .InSingletonScope() 
    .Named(BindingNames.SHARED_CACHE); 

Bind<ICache>().ToMethod(ctx => FactoryMethods.CreateTwoTierCache(
    ctx.Kernel.Get<ICache>(BindingNames.SHARED_CACHE), 
    ctx.Kernel.Get<IZZZ>())) 
    .InSingletonScope(); 

을 나는 클래스가 두 가지를 사용하려면 대부분의 시간 동일한 인터페이스 (예 : ICache) 인 1 차 캐시 따라서 속성 제한을 사용하여 공유 캐시의 사용을 제한합니다 (공유 캐시에 직접 액세스해야하는 클래스는 [SharedCache] 만 사용할 수 있습니다).

ctx.Kernel.Get<ICache>(BindingNames.SHARED_CACHE), 

가 일치 바인딩 아마도 때문에 제 1 결합에 속성 제약 사용할 수 없다는 예외 발생된다

이제, 문제는 제 2 결합 특이이 라인이다.

첫 번째 바인딩의 해상도 결과를 두 번째 바인딩의 팩토리 메서드에 삽입하려면 어떻게해야합니까?

해결 방법 :

은 현재 내가 Parameter 첫 번째 바인딩에 더 복잡한 When() 기반 제약 조건을 사용하고 있습니다. 내 바인딩은 이제 다음과 같이 보입니다.

Bind<ICache>().ToMethod(ctx => FactoryMethods.CreateCache(
     ctx.Kernel.Get<IXXX>(), 
     ctx.Kernel.Get<IYYY>())) 
    .When(o => (o.Target != null && 
     o.Target.GetCustomAttributes(typeof (SharedCacheAttribute), false).Any()) || 
     o.Parameters.Any(p => p.Name == ParameterNames.GET_SHARED_CACHE)) 
    .InSingletonScope(); 

Bind<ICache>().ToMethod(ctx => FactoryMethods.CreateTwoTierCache(
    ctx.Kernel.Get<ICache>(new Parameter(ParameterNames.GET_SHARED_CACHE, true, true)), 
    ctx.Kernel.Get<IZZZ>())) 
    .InSingletonScope(); 

의도 한대로 작동하지만 구문이 복잡합니다. 또한 GET_SHARED_CACHE 매개 변수가 하위 요청에 전달되지 않도록하려면 생성자의 'shouldInherit'인수가 false으로 설정되어야한다고 예상했을 것입니다. 결과적으로이 값을 false으로 설정하면 StackOverflowException이됩니다. false로 설정하면 매개 변수가 여러 요청간에 지속됩니다. true으로 설정하면 전파되지 않습니다. 예상했던 것의 반대입니다.

답변

2

대체 방법은 SharedCacheAttributeNamedAttribute으로 대체하는 것입니다. 다음 예는 다음과 같습니다

//bindings 
Bind<ICache>().ToMethod(ctx => FactoryMethods.CreateCache(
    ctx.Kernel.Get<IXXX>(), 
    ctx.Kernel.Get<IYYY>())) 
.InSingletonScope() 
.Named(BindingNames.SHARED_CACHE); 

Bind<ICache>().ToMethod(ctx => FactoryMethods.CreateTwoTierCache(
    ctx.Kernel.Get<ICache>(BindingNames.SHARED_CACHE), 
    ctx.Kernel.Get<IZZZ>())) 
.InSingletonScope(); 

// cache users 
public class UsesSharedCache 
{ 
    public UsesSharedCache([Named(BindingNames.SHARED_CACHE)] ICache sharedCache) 
    { 
    } 
} 

public class UsesDefaultCache 
{ 
    public UsesDefaultCache(ICache defaultCache) 
    { 
    } 
} 

또 다른 대안은 IProvider 될 것이다. 다음은이 같을 것이다 바인딩 :

Bind<ICache>().ToProvider<CacheProvider>(); 

CacheProvider는 "기본"또는 공유 캐시를 검색할지 여부를 결정하는 로직을 포함한다. 특성을 확인한 다음 해당 인스턴스를 확인하고 반환해야합니다. 그래서 ICache 두 개라는 이름의 바인딩이있을 필요가있을 것이다 :

Bind<ICache>().ToMethod(...).Named("default") 
       .BindingConfiguration.IsImplicit = true; 
Bind<ICache>().ToMethod(...).Named("shared"); 
       .BindingConfiguration.IsImplicit = true; 

비고 : 그렇지 Ninject에가 (이름없이) ICache에 대한 요청을 고려 모든 바인딩에 의해 충족되어야하기 때문에 .BindingConfiguration.IsImplicit = true;이 필요 - 예외가 발생합니다. 요청은 제공자에 의해서만 채워 져야합니다.

+0

나는 이것이 적절한 대안이라고 생각합니다. 나는 원래'Named' 속성을 사용하는 것에 대해 생각해 보았습니다.하지만 생성자에서 속성을 포함하는 클래스에 Ninject 의존성을 추가 했으므로 사용하지 않으려했습니다. 그러나 IProvider 솔루션은 이러한 문제를 겪지 않습니다.공급자는 Ninject 모듈과 동일한 프로젝트에 남아있을 수 있으며 바인딩은 비교적 복잡하지 않습니다. 공급자 메서드를 시도하고 내 설정을 단순화하는지 확인합니다. –

+0

불행히도 공급자 경로가 작동하지 않았습니다. 그 로직을 가진 CacheProvider를 만들었지 만 삽입 할 때 CacheProvider뿐만 아니라 두 개의 명명 된 바인딩에도 일치했습니다. 둘 이상의 일치하는 바인딩을 사용할 수 있습니다. 매칭 바인딩 : 1) ICACHE에서 방법 결합 방법 2)에 ICACHE 바인딩 ICACHE 행 ( 가되는 것을 바인딩을 중지하지 않는 명명 같다)의 CacheProvider 통해 ICACHE 결합 3) 공급자 기본적으로 삽입됩니다. –

+0

명명 된 ICache 바인딩에 ".BindingConfiguration.IsImplicit = true"를 추가하여 작동 시켰습니다. 이제 예상대로 작동합니다! 나는 여기에서 아이디어를 얻었다 : http://stackoverflow.com/questions/5997483/ninject-default-contextual-binding –