2017-10-12 176 views
1

這是一個後續行動Generic Interface dependency injection into factoryNinject綁定通用接口

答案是正確的,但我過於簡單的代碼。因爲在界面上使用out參數,所以不能將TOrderRequest作爲create方法中的輸入參數。並且在界面上使用Out和In時,綁定將不再起作用。

那麼你如何將這與Ninject綁定?

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混淆你想達到什麼」

反正這裏的東西可能符合您需要。它主要依靠CanHandle方法ICreateOrders

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

由於HorseOrderCreator關閉泛型類型,它真的沒有意義將其綁定到一個開放通用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

謝謝你的回答。我明白了你的觀點,但是當這樣做的時候仍然沒有注入工廠。 – MacGyver

+0

@MacGyver是的,對不起,相應地更新了我的答案。 – BatteryBackupUnit