2017-03-18 16 views
1

Simple Injector DIコンテナを使用して複数の具体的なタイプのIShipperインターフェイスを登録し、nameを使用して動的に選択する方法を教えてください。SimpleInjectorを使用して具体的な名前のオブジェクトを動的に選択

同じタイプの複数のインスタンスを登録できない場合は、Simple Injectorとは別の方法がありますか?

public Setup() 
{ 
    var container = new SimpleInjector.Container(); 
    // TODO: Registration required for two different shippers 
    container.Register<UPS, IShipper>(); 
} 

public interface IShipper 
{ 
    void Ship(Product product) 
} 

public class UPS : IShipper { ... } 

public class FedEx : IShipper { ... } 

public void Ship(String shipper, Product product) 
{ 
    // TODO: Retrieve the shipper by name 
    var shipper = container.GetInstance<IShipper>(); 
    shipper.Ship(product); 
} 

Ship("FedEx", new Product()); 

答えて

3

これを行うための多くの方法は、例えば、あなたは可能性があります:

  • IShipperを取得できるようにIShipperFactoryを定義します。
  • IShipperを実装し、実際のIShipper実装に代理人を作成します。 Productエンティティ自体に荷送人に関する情報が含まれている場合にこの機能が有効になります。
  • 'ディスパッチャthat forwards the call to the proper IShipper internally, without exposing this IShipper`をクライアントに戻す抽象化を作成します。

ドキュメントhereは、同じ抽象化の複数の登録を作成する方法に関するいくつかの手がかりを与えます。ここで

は、ディスパッチャの使用例です:

public Setup() 
{ 
    var container = new Container(); 

    var shippers = new Dictionary<string, InstanceProducer<IShipper>> 
    { 
     { "FedEx", Lifestyle.Transient.CreateProducer<IShipper, FedEx>(container) }, 
     { "UPS", Lifestyle.Transient.CreateProducer<IShipper, UPS>(container) }, 
    }; 

    container.RegisterSingleton<IShippingDispatcher>(
     new ShippingDispatcher(shipper => shippers[shipper].GetInstance())); 
} 
:例として

public interface IShippingDispatcher 
{ 
    void Ship(string shipper, Product product); 
} 

public class ShippingDispatcher : IShippingDispatcher 
{ 
    private readonly Func<string, IShipper> factory; 
    public ShippingDispatcher(Func<string, IShipper> factory) { this.factory = factory; } 
    public void Ship(string shipper, Product product) => factory(shipper).Ship(product); 
} 

を、あなたはこれで、次の設定を持つことができます

2

これについてはいくつかの方法があります。 https://simpleinjector.readthedocs.io/en/latest/using.html#collections https://simpleinjector.readthedocs.io/en/latest/howto.html#resolve-instances-by-key

あなたが説明しているアプローチは、2番目のリンクのように聞こえます。しかし、私は、一般的に最初のリンクで説明したアプローチで行くとIShipperインターフェイスにプロパティNameを追加し、同じような何かをするだろうvar shipper = shippers.FirstOrDefault(x => x.Name == "FedEx");

public interface IShipper 
{ 
    string Name { get; } 
    void Ship(Product product) 
} 

public Setup() 
{ 
    var container = new SimpleInjector.Container(); 
    // TODO: Registration required for two different shippers 
    container.RegisterCollection<IShipper>(new[] { new UPS(), new FedEx() }); 
} 

public void Ship(string shipperName, Product product) 
{ 
    // TODO: Retrieve the shipper by name 
    var shippers = container.GetAllInstances<IShipper>(); 
    var shipper = shippers.FirstOrDefault(x => x.Name == shipperName); 
    // TODO: do null check on shipper 
    shipper.Ship(product); 
} 
関連する問題