I'm playing around with DI and Ninject. I'm open for suggestions on how to solve this in another way. I'm trying to make sure the concrete implementations of ICreateOrders can be replaced - if need be. Maybe there's another way or pattern?
Solutions like this: C# - Ninject, IoC and factory pattern are fine but I was hoping to inject the possible creators into the factory and making the factory pick one based on OrderRequest.
This doesn't work.
kernel.Bind(typeof(ICreateOrders<,>)).To(typeof(OrderCreator))
I can kind of understand why not. But even another signature of OrderCreator to OrderCreator<,> or actually providing the Interfaces and/or concrete classes to the generic parameters don't work and ideally, I don't want to do that because the implementor of a new OrderCreator should just do something like this
public class HorseOrderCreator : ICreateOrders<HorseOrderRequest, HorseOrderResponse>
{
public HorseOrderResponse Create()
{
throw new NotImplementedException();
}
}
Sample code
using System;
using Ninject;
using System.Collections.Generic;
using System.Linq;
namespace NinjectPlatyGround
{
class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel();
kernel.Bind(typeof(ICreateOrders<,>)).To(typeof(OrderCreator));
kernel.Bind<IOrderCreatorFactory>().To<OrderCreatorFactory>();
var factory = kernel.Get<IOrderCreatorFactory>();
var orderCreator = factory.GetOrderCreator(new OrderRequest());
}
}
public class OrderRequest : IOrderRequest
{
}
public class OrderResponse : IOrderResponse
{
}
public class OrderCreator : ICreateOrders<OrderRequest, OrderResponse>
{
public OrderResponse Create()
{
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.
return this.createOrders.First();
}
}
public interface ICreateOrders<TOrderRequest, TOrderResponse> where TOrderRequest : IOrderRequest where TOrderResponse : IOrderResponse
{
TOrderResponse Create();
}
public interface IOrderCreatorFactory
{
ICreateOrders<IOrderRequest, IOrderResponse> GetOrderCreator(IOrderRequest orderRequest);
}
public interface IOrderRequest
{
}
public interface IOrderResponse
{
}
}
I'm aware that I need to inject multiple concrete instances of ICreatorOrders to make Ninject give me an IEnumerable in the factory. Just pointing out with the code what I'm actually trying to do.