[英]Ninject bind generic interface
這是Generic Interface 依賴注入到 factory的后續
答案是正確的,但我過度簡化了代碼。 因為沒有接口上的參數,您不能將 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
{
}
}
這就是我在您之前的問題“Create 的空實現和 this.createOrders.First() 有點混淆了您想要實現的目標”中的評論要點
無論如何,這里有一些可能符合您需求的東西。 它主要依賴於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
{
}
}
由於HorseOrderCreator
是一個封閉的泛型類型,將它綁定到一個開放的泛型typeof(ICreateOrders<,>)
確實沒有意義。 畢竟, HorseOrderCreator
永遠不可能是ICreateOrders<Foo, Bar>
!
此外,無論什么 DI 容器,您當前的代碼都將永遠無法工作。 嘗試這個:
ICreateOrders<IOrderRequest, IOrderResponse> createOrders =
(ICreateOrders<IOrderRequest, IOrderResponse>)new HorseOrderCreator();
結果是:
System.InvalidCastException 無法將“HorseOrderCreator”類型的對象強制轉換為“ICreateOrders`2[NinjectPlayGround.IOrderRequest,NinjectPlayGround.IOrderResponse]”。
因此,鑒於當前的接口約束,您的工廠將永遠無法返回HorseOrderCreator
。
所以這是一個設計問題。 不是DI問題。 並且該設計還可能包括界面的使用者,這些使用者並未在問題中提供。 所以我建議包括它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.