2016-06-22 8 views
0

したがって、autofacを使用している間、傍受の概念を実装しようとしています。ダイナミックな傍受を実装するのと同じように、私は具体的なコードを持っているすべてのクラスのように、何も気にしません。AutoFacインターセプト、内部と外部を区別する方法

マイコード(ない私の実際のコードは、私はこのオンラインを見つけたが、それは私の問題は、私は私のプロダクトマネージャーは、IProductServiceのための「CachedProductService」を受信したい、と私は私のCachedProductServiceをしたい、ある

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

私の問題を示していますIProductServiceのための「DefaultProductService」を受信する。

を私はいくつかの解決策を知っているが、それらのどれも正確に正しいようではありません。これを行うための正しい方法は何ですか?

ありがとう! マイケル

+0

あなたの 'CachedProductService'はデコレータです:http://docs.autofac.org/en/latest/advanced/adapters-decorators.html。 – Steven

答えて

1

これはnamed dependenciesを使用して行うことができます。

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

あなたが望むどの実装を示すために、マニュアルに記載され、いくつかの異なる方法があります。このよう
の代わりに、あなたが自分の名前で区別2つの実装があるでしょう、IProductServiceの実装がDefaultProductServiceであることを言って、与えられたクラスに注入する。これは、最も簡単で明確なようになっています。それは、コンテナへの依存性を持っているクラスが発生するため

public class ProductManager : IProductManager 
{ 
    private readonly IProductService _productService; 

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

は正直に言うと、私はそれを好きではありません。これは、クラス自体から完全に分離して構成することはできません。 Windsorを使用すると、依存関係をコンテナに登録し、使用する名前付き依存関係を通知するときにこれを実行できます。

しかし、これはうまくいくはずです。

0

Scottの提案に基づいて、私はProductManagerクラスのコンテナに依存関係を導入する必要がない方法を考え出したと思います。私は単にCachedProductServiceをインスタンス化し、傍受概念ではなく、デコレータの概念ではないと思われるProductServiceが何をしようとする

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

これは動作しますが、反復可能なパターンではない可能性があります。この場合、 'CachedProductService'は1つの依存関係しか持たないので、ここで新しいものを作ることができます。しかし、他のケースでは、このようなクラスは複数の依存関係を持つことがあり、これらのクラスは独自の依存関係を持つ可能性があります。したがって、コンストラクタを呼び出すと、それらの依存関係をすべて提供する必要があります。コンテナに*すべて*を解決させ、クラスの新しいインスタンスを作成させない方法を理解することが最善です。 –

1

を使用するためにそれを伝えることができます。

オブジェクト指向プログラミングでは、デコレータパターンは、同じクラスの他のオブジェクトの動作に影響を与えることなく、静的または動的に個々のオブジェクトに動作を追加できるデザインパターンです。
Decorator pattern (Wikipedia)

Decorator pattern

からAutofacが組み込まれていデコレータのサポートという名前の登録を使用しました。

まず、あなたが名前の登録とあなたの基本コンポーネントとデコレータを宣言する必要があります。

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を参照してください。

関連する問題