Ninject bind 泛型接口



这是对通用接口依赖项注入工厂的后续

答案是正确的,但我过度简化了代码。因为接口上没有 out 参数,您不能将 TOrderRequest 作为创建方法中的输入参数。在接口上使用 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() 的空实现在某种程度上混淆了你想要实现的目标"中的评论要点"

无论如何,这里有一些可能符合您需求的东西。它主要依赖于ICreateOrders中的CanHandle方法

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 问题。该设计还可能包括接口的使用者,这些问题中未提供。所以我建议将它们包括在内。

最新更新