2017-10-12 141 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