簡體   English   中英

Ninject 綁定通用接口

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM