I have an interface called IXmlStrategy which has declared another Interface like this:
namespace IceServices.Business.Interfaces.Strategies
{
public interface IXmlStrategy
{
IGetPersonNameXmlStrategy GetPersonNameXmlStrategy { get; }
}
}
I expect there to be many strategy interfaces and I want to put all of them in once interface so I don't have to inject 10-20 IXmlStrategy variants.
This is my class using DI:
using System.Linq;
using IceServices.Business.Interfaces.Commands;
using IceServices.Business.Interfaces.Configurations;
using IceServices.Business.Interfaces.Deserializers;
using IceServices.Business.Interfaces.Mappers;
using IceServices.Business.Interfaces.Services;
using IceServices.Business.Interfaces.Strategies;
using IceServices.DomainObjects.ResponseObjects;
namespace IceServices.Business.Commands
{
public class IpdCommands : IIpdCommands
{
private readonly ISoapService _soapService;
private readonly IUrlConfigurations _urlConfigurations;
private readonly IXmlDeserializer _xmlDeserializer;
private readonly IDomainObjectMapper _domainObjectMapper;
private readonly IXmlStrategy _xmlStrategy;
public IpdCommands(ISoapService soapService, IUrlConfigurations urlConfigurations, IXmlDeserializer xmlDeserializer, IDomainObjectMapper domainObjectMapper, IXmlStrategy xmlStrategy)
{
_soapService = soapService;
_urlConfigurations = urlConfigurations;
_xmlDeserializer = xmlDeserializer;
_domainObjectMapper = domainObjectMapper;
_xmlStrategy = xmlStrategy;
}
public PersonNameResponse GetPersonName(int id)
{
var webServiceXmlString = _xmlStrategy.GetPersonNameXmlStrategy.GetXml(id.ToString());
var listOfProperties = typeof(PersonNameResponse).GetProperties().Select(expr => expr.Name);
var xmlStringResponse = _soapService.CallWebService(_urlConfigurations.GetPersonFirstname, webServiceXmlString);
var stringArrayOfProperties = listOfProperties as string[] ?? listOfProperties.ToArray();
var dictionaryData = _xmlDeserializer.DeserializeXmlToDictionary(stringArrayOfProperties, xmlStringResponse);
return _domainObjectMapper.MapDictionaryToObject<PersonNameResponse>(dictionaryData, stringArrayOfProperties);
}
}
}
as you can see I'm calling GetPersonNameXmlStrategy.GetXml(id) like this:
var webServiceXmlString = _xmlStrategy.GetPersonNameXmlStrategy.GetXml(id.ToString());
However I get a runtime error because IOC doesn't understand how to resolve it's dependency:
{"Message":"An error has occurred.","ExceptionMessage":"An error occurred when trying to create a controller of type 'IpdController'. Make sure that the controller has a parameterless public constructor.","ExceptionType":"System.InvalidOperationException","StackTrace":" at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)\r\n at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()","InnerException":{"Message":"An error has occurred.","ExceptionMessage":"Error activating IXmlStrategy using binding from IXmlStrategy to XmlStrategy\r\nNo constructor was available to create an instance of the implementation type.\r\n\r\nActivation path:\r\n 3) Injection of dependency IXmlStrategy into parameter xmlStrategy of constructor of type IpdCommands\r\n 2) Injection of dependency IIpdCommands into parameter ipdCommands of constructor of type IpdController\r\n 1) Request for IpdController\r\n\r\nSuggestions:\r\n 1) Ensure that the implementation type has a public constructor.\r\n 2) If you have implemented the Singleton pattern, use a binding with InSingletonScope() instead.\r\n","ExceptionType":"Ninject.ActivationException","StackTrace":" at Ninject.Activation.Providers.StandardProvider.Create(IContext context)\r\n at Ninject.Activation.Context.ResolveInternal(Object scope)\r\n at Ninject.Activation.Context.Resolve()\r\n at System.Linq.Enumerable.WhereSelectEnumerableIterator
2.MoveNext()\r\n at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable
1 source)\r\n at System.Linq.Enumerable.WhereSelectArrayIterator2.MoveNext()\r\n at System.Linq.Buffer
1..ctor(IEnumerable1 source)\r\n at System.Linq.Enumerable.ToArray[TSource](IEnumerable
1 source)\r\n at Ninject.Activation.Providers.StandardProvider.Create(IContext context)\r\n at Ninject.Activation.Context.ResolveInternal(Object scope)\r\n at Ninject.Activation.Context.Resolve()\r\n at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()\r\n at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable
1 source)\r\n at System.Linq.Enumerable.WhereSelectArrayIterator2.MoveNext()\r\n at System.Linq.Buffer
1..ctor(IEnumerable1 source)\r\n at System.Linq.Enumerable.ToArray[TSource](IEnumerable
1 source)\r\n at Ninject.Activation.Providers.StandardProvider.Create(IContext context)\r\n at Ninject.Activation.Context.ResolveInternal(Object scope)\r\n at Ninject.Activation.Context.Resolve()\r\n at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()\r\n at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable
1 source)\r\n at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)\r\n at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)"}}
This is my IOC setup in Ninject.WebCommon:
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IIpdCommands>().To<IpdCommands>();
kernel.Bind<IUrlConfigurations>().To<UrlConfigurations>();
kernel.Bind<IXmlDeserializer>().To<XmlDeserializer>();
kernel.Bind<IXmlDocumentFactory>().To<XmlDocumentFactory>();
kernel.Bind<IDomainObjectMapper>().To<DomainObjectMapper>();
kernel.Bind<ISoapService>().To<SoapService>();
kernel.Bind<IXmlStrategy>().To<XmlStrategy>();
kernel.Bind<IGetPersonNameXmlStrategy>().To<GetPersonNameXmlStrategy>();
}
I need to change how the binding works for IGetPersonNameXmlStrategy but I'm not sure how. Does anyone know how I can get Ninject to resolve the depedency through IXmlStrategy.IGetPersonNameXmlStrategy ?