2016-06-22 11 views
0

그래서 자동 차단을 사용하면서 차단 개념을 구현하려고합니다. 역동적 인 인터셉트를 구현하는 것과 같은 구체적인 것은하지 않습니다. 모든 클래스에 구체적인 코드가 있습니다.자동 차단 (AutoFac) 차단, 내부를 외부와 구분하는 방법

내 코드 (나의 실제 코드는,이 온라인을 발견하지만 내 문제가

public class DefaultProductService : IProductService 
{  
    public Product GetProduct(int productId) 
    { 
     return new Product(); 
    } 
} 

public class CachedProductService : IProductService 
{ 
    private readonly IProductService _innerProductService; 
    private readonly ICacheStorage _cacheStorage; 

    public CachedProductService(IProductService innerProductService, ICacheStorage cacheStorage) 
    { 
     if (innerProductService == null) throw new ArgumentNullException("ProductService"); 
     if (cacheStorage == null) throw new ArgumentNullException("CacheStorage"); 
     _cacheStorage = cacheStorage; 
     _innerProductService = innerProductService; 
    } 

    public Product GetProduct(int productId) 
    { 
     string key = "Product|" + productId; 
     Product p = _cacheStorage.Retrieve<Product>(key); 
     if (p == null) 
     { 
      p = _innerProductService.GetProduct(productId); 
      _cacheStorage.Store(key, p); 
     } 

     return p; 
    } 
} 

public class ProductManager : IProductManager 
{ 
    private readonly IProductService _productService; 

    public ProductManager(IProductService productService) 
    { 
     _productService = productService; 
    } 
} 

, 내 ProductManager이 IProductService에 대해 "CachedProductService"을 수신 할 내 문제를 보여줍니다, 그리고 내 CachedProductService을 원한다 IProductService에 대한 "DefaultProductService"를받을 수 있습니다.

을 나는 몇 가지 해결책을 알고 있지만, 그들 중 누구도 정확히 올바른 보이지 않는다. 어떻게이 일을 올바른 방법인가?

감사합니다! 마이클

+0

귀하의'CachedProductService'는 데코레이터입니다 : http://docs.autofac.org/en/latest/advanced/adapters-decorators.html. – Steven

답변

1

named dependencies을 사용하면됩니다.
대신 IProductService의 구현 DefaultProductService 것을 말하고, 당신은이 같은 자신의 이름으로 구별이 구현을해야합니다 :

builder.Register<DefaultProductService>().Named<IProductService>("DefaultProductService"); 
builder.Register<CachedProductService>().Named<IProductService>("CachedProductService"); 

당신이 원하는 구현을 나타 내기 위해 문서에 설명 된 몇 가지 방법이 있습니다 주어진 클래스에 주입 할 수 있습니다. 이것은 가장 간단하고 명시 적으로 다음과 같습니다가 컨테이너에 대한 종속성을 가지고 클래스를 유발하기 때문에

public class ProductManager : IProductManager 
{ 
    private readonly IProductService _productService; 

    public ProductManager([WithKey("CachedProductService")]IProductService productService) 
    { 
     _productService = productService; 
    } 
} 

것은 솔직히 말해서, 나는 그것을 좋아하지 않아. 클래스 자체와 완전히 별도로 구성 할 수는 없습니다. Windsor를 사용하면 컨테이너와의 종속성을 등록 할 때 사용할 이름 지정 종속성을 알려줍니다.

하지만 이렇게하면됩니다.

0

Scott의 제안에 따라 필자는 ProductManager 클래스의 컨테이너에 종속성을 도입하지 않고도 방법을 알아 냈다고 생각합니다. 나는 단순히 CachedProductService를 인스턴스화하고 당신이 할하려는 것은 차단 개념 오히려 장식 개념 수없는 것 같다

builder.RegisterType(typeof(ProductService)).Named<IProductService>("DefaultProductService"); 
builder.Register(c => new CachedProductService(c.ResolveKeyed<IProductService>("DefaultProductService"))).As<IProductService>(); 
+0

이 방법은 효과가 있지만 반복되는 패턴이 아닐 수 있습니다. 이 경우'CachedProductService'는 오직 하나의 의존성을 가지므로 여기서 새로운 것을 생성 할 수 있습니다. 그러나 다른 경우에는 이와 같은 클래스가 둘 이상의 종속성을 가질 수 있으며,이 클래스는 자신의 종속성을 가질 수 있습니다. 따라서 생성자를 호출하면 모든 종속성을 제공해야합니다. 컨테이너가 * everything *을 처리하고 클래스의 새 인스턴스를 생성하지 않는 방법을 찾는 것이 가장 좋습니다. –

1

사용하도록하는 ProductService을 알 수 있습니다.

개체 지향 프로그래밍에서 데코레이터 패턴은 동일한 클래스의 다른 개체의 동작에 영향을주지 않고 정적 또는 동적으로 개별 개체에 동작을 추가 할 수있는 디자인 패턴입니다.
Autofac

Decorator pattern

Decorator pattern (Wikipedia)에서가 내장 된 이름 등록을 사용하여 장식에 대한 지원.

첫째, 당신이 당신의 기본 구성 요소와 이름이 등록 등의 장식을 선언해야 :

builder.RegisterType<DefaultProductService>().Named<IProductService>("base"); 
builder.RegisterType<CacheProductServiceAdapter>().Named<IProductService>("cache"); 

그런 다음 당신은 당신도 할 수 있습니다

builder.RegisterDecorator((c, inner) => c.ResolveNamed<IProductService>("cache", TypedParameter.From(inner)), fromKey : "base") 
     .As<IProductService>(); 

당신의 장식 등록 할 수 있습니다 더 하나의 어댑터 이상 :

builder.RegisterType<DefaultProductService>().Named<IProductService>("base"); 
builder.RegisterType<CacheProductServiceAdapter>().Named<IProductService>("cache"); 
builder.RegisterType<LoggingProductServiceAdapter>().Named<IProductService>("logging"); 

builder.RegisterDecorator((c, inner) => c.ResolveNamed<IProductService>("cache", TypedParameter.From(inner)), fromKey : "base", toKey:"cached"); 
builder.RegisterDecorator((c, inner) => c.ResolveNamed<IProductService>("logging", TypedParameter.From(inner)), fromKey : "cached") 
     .As<IProductService>(); 

자세한 내용은 adapters and decorators from Autofac documentation을 참조하십시오.