2017-10-12 9 views
1

をバインドNinjectこれはGeneric Interface dependency injection into factoryは汎用インタフェースに

にフォローアップ答えが正しいとされたが、私は、コードを単純化。インターフェイスのoutパラメータを使用すると、createメソッドでTOrderRequestを入力パラメータとして使用できないためです。インターフェイス上でOutとInを使用すると、バインディングは再び機能しません。

これをNinjectとどうやって結びつけますか? HorseOrderCreator以来

using System; 
using Ninject; 
using System.Collections.Generic; 
using System.Linq; 

namespace NinjectPlayGround 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var kernel = new StandardKernel(); 

      //How to bind this? 
      kernel.Bind(typeof(ICreateOrders<,>)).To<HorseOrderCreator>(); 
      //kernel.Bind<ICreateOrders<IOrderRequest, IOrderResponse>>().To(typeof(OrderCreator)); 

      kernel.Bind<IOrderCreatorFactory>().To<OrderCreatorFactory>(); 

      var factory = kernel.Get<IOrderCreatorFactory>(); 

      var orderCreator = factory.GetOrderCreator(new OrderRequest()); 
      var create = orderCreator.Create(new OrderRequest()); 

     } 
    } 
    public class OrderRequest : IOrderRequest 
    { 

    } 
    public class OrderResponse : IOrderResponse 
    { 

    } 
    public class HorseOrderRequest : IOrderRequest 
    { 

    } 
    public class HorseOrderResponse : IOrderResponse 
    { 
     public string HorseName { get; set; } 
    } 
    public class HorseOrderCreator : ICreateOrders<HorseOrderRequest, HorseOrderResponse> 
    {   
     public HorseOrderResponse Create(HorseOrderRequest orderRequest) 
     { 
      return new HorseOrderResponse() { HorseName = "Fred" }; 
     } 
    } 
    public class OrderCreator : ICreateOrders<OrderRequest, OrderResponse> 
    {   

     public OrderResponse Create(OrderRequest orderRequest) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
    public class OrderCreatorFactory : IOrderCreatorFactory 
    { 
     private readonly IEnumerable<ICreateOrders<IOrderRequest, IOrderResponse>> createOrders; 
     public OrderCreatorFactory(IEnumerable<ICreateOrders<IOrderRequest, IOrderResponse>> createOrders) 
     { 
      this.createOrders = createOrders; 
     } 

     public ICreateOrders<IOrderRequest, IOrderResponse> GetOrderCreator(IOrderRequest orderRequest) 
     { 
      //Based on orderRequest i find the implementation i need. 
     } 
    } 
    public interface ICreateOrders<TOrderRequest, TOrderResponse> where TOrderRequest : IOrderRequest where TOrderResponse : IOrderResponse 
    { 
     TOrderResponse Create(TOrderRequest orderRequest); 
    } 
    public interface IOrderCreatorFactory 
    { 
     ICreateOrders<IOrderRequest, IOrderResponse> GetOrderCreator(IOrderRequest orderRequest); 
    } 
    public interface IOrderRequest 
    { 

    } 
    public interface IOrderResponse 
    { 

    } 
} 

答えて

1

あなたの前の質問での私のコメントのポイントだった「作成の空の実装とthis.createOrders.First()somewhateはあなたが達成したいものを難読化」とにかくここ

すると、あなたにマッチかもしれない何かでありますニーズ。これは、主に

using System; 
using Ninject; 
using System.Collections.Generic; 
using System.Linq; 

namespace NinjectPlayGround 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var kernel = new StandardKernel(); 

      //How to bind this? 
      kernel.Bind<ICreateOrders<IOrderRequest, IOrderResponse>>().To(typeof(OrderCreator)); 
      kernel.Bind<ICreateOrders<IOrderRequest, IOrderResponse>>().To(typeof(HorseOrderCreator)); 

      kernel.Bind<IOrderCreatorFactory>().To<OrderCreatorFactory>(); 

      var factory = kernel.Get<IOrderCreatorFactory>(); 

      var orderCreator = factory.GetOrderCreator(new OrderRequest()); 
      var orderResponse = orderCreator.Create(new OrderRequest());  
      if (!(orderResponse is OrderResponse)) throw new InvalidCastException(); 

      var horseOrderCreator = factory.GetOrderCreator(new HorseOrderRequest()); 
      var horseResponse = horseOrderCreator.Create(new HorseOrderRequest());  
      if (!(horseResponse is HorseOrderResponse)) throw new InvalidCastException(); 

      Console.WriteLine("All resolutions successfull"); 
      Console.ReadLine(); 

     } 
    } 
    public class OrderRequest : IOrderRequest 
    { 

    } 
    public class OrderResponse : IOrderResponse 
    { 

    } 
    public class HorseOrderRequest : IOrderRequest 
    { 

    } 
    public class HorseOrderResponse : IOrderResponse 
    { 
     public string HorseName { get; set; } 
    } 

    public abstract class BaseOrderCreator<TOrderRequest, TOrderResponse> : ICreateOrders<IOrderRequest, IOrderResponse> where TOrderRequest : IOrderRequest where TOrderResponse : IOrderResponse 
    { 
     public bool CanHandle(IOrderRequest request) 
     { 
      return request is TOrderRequest; 
     } 

     public abstract TOrderResponse SpecificCreate(TOrderRequest orderRequest); 

     public IOrderResponse Create(IOrderRequest orderRequest) 
     { 
      return this.SpecificCreate((TOrderRequest)orderRequest); 
     } 
    } 

    public class HorseOrderCreator : BaseOrderCreator<HorseOrderRequest, HorseOrderResponse> 
    { 
     public override HorseOrderResponse SpecificCreate(HorseOrderRequest orderRequest) 
     { 
      return new HorseOrderResponse() { HorseName = "Fred" }; 
     } 
    } 
    public class OrderCreator : BaseOrderCreator<OrderRequest, OrderResponse> 
    { 
     public override OrderResponse SpecificCreate(OrderRequest orderRequest) 
     { 
      return new OrderResponse(); 
     } 
    } 
    public class OrderCreatorFactory : IOrderCreatorFactory 
    { 
     private readonly IEnumerable<ICreateOrders<IOrderRequest, IOrderResponse>> createOrders; 
     public OrderCreatorFactory(IEnumerable<ICreateOrders<IOrderRequest, IOrderResponse>> createOrders) 
     { 
      this.createOrders = createOrders; 
     } 

     public ICreateOrders<IOrderRequest, IOrderResponse> GetOrderCreator(IOrderRequest orderRequest) 
     { 
      return createOrders.FirstOrDefault(co => co.CanHandle(orderRequest)); 
     } 
    } 
    public interface ICreateOrders<in TOrderRequest, out TOrderResponse> where TOrderRequest : IOrderRequest where TOrderResponse : IOrderResponse 
    { 
     bool CanHandle(IOrderRequest request); 

     TOrderResponse Create(TOrderRequest orderRequest); 
    } 
    public interface IOrderCreatorFactory 
    { 
     ICreateOrders<IOrderRequest, IOrderResponse> GetOrderCreator(IOrderRequest orderRequest); 
    } 
    public interface IOrderRequest 
    { 

    } 
    public interface IOrderResponse 
    { 

    } 
} 
+0

ブリリアント。ありがとう@jbl。 – MacGyver

0

ジェネリック型を閉じて、それは本当にオープンジェネリックtypeof(ICreateOrders<,>)にバインドしても意味がありませんです。結局のところ、HorseOrderCreatorとなることはありません。は​​です!

また、DIコンテナに関係なく、現在のコードは動作しません。 これを試してみてください:

ICreateOrders<IOrderRequest, IOrderResponse> createOrders = 
    (ICreateOrders<IOrderRequest, IOrderResponse>)new HorseOrderCreator(); 

結果に:

System.InvalidCastExceptionの 型のオブジェクトをキャストすることができません 'HorseOrderCreator' 'ICreateOrders`2 [NinjectPlayGround.IOrderRequest、NinjectPlayGround.IOrderResponseを]' と入力します。

だからあなたの工場は決してHorseOrderCreator与えられた現在のインタフェースの制約を返すことができるようになります。

これは設計上の問題です。 DIの問題ではありません。また、そのデザインにはインターフェイスの消費者も含まれていますが、質問には含まれていません。だから私はそれらを含めることを提案する。

+0

ICreateOrdersが答えてくれてありがとうでCanHandle方法に依存しています。私はあなたのポイントを得るが、これを行うときには、まだ工場に注入されていません。 – MacGyver

+0

@MacGyverええ、申し訳ありません、それに応じて私の答えを更新しました。 – BatteryBackupUnit

関連する問題