views:

146

answers:

1

I've set up DI with Ninject in my ASP.NET MVC application like this

            Bind<IRepository>().To<XmlDefaultRepository>().WhenInjectedInto(typeof(PageController)).WithConstructorArgument("contentType", ContentType.Page);
            Bind<IRepository>().To<XmlDefaultRepository>().WhenInjectedInto(typeof(WidgetController)).WithConstructorArgument("contentType", ContentType.Page);
            Bind<IRepository>().To<XmlDefaultRepository>().WhenInjectedInto(typeof(SectionController)).WithConstructorArgument("contentType", ContentType.Section);
            Bind<IRepository>().To<XmlDefaultRepository>().WhenInjectedInto(typeof(WidgetZoneController)).WithConstructorArgument("contentType", ContentType.WidgetZone);

XmlDefaultRepository implements IRepository and it contains a constructor that takes contentType parameter which I use for persistance path generation.

Now I have a ServicesController which does not have a default type by itself - it is just a controller that provides JSON data (JSON actions) to consumers from jQuery.

This is how it looks now:

    public class ServicesController : ContentController
    {
        public ActionResult ContentSlugs(string contentType, string q, int limit)
        {
            IRepository _repository = new XmlDefaultRepository(contentType); // this instantiation depends on contentType provided by JSON GET request at runtime and I want to somehow replace it with DI
            return Json(_repository.GetSlugsForContentType(limit, q), JsonRequestBehavior.AllowGet);
        }
}

And this is how other controllers look like (DI is done thru constructor injection here):

public class SectionController : ContentController
        {
private IRepository ContentRepository;
            public SectionController(IRepository repository)
            {
                ContentRepository = repository;
            }
    }

How can I get rid of "new XmlDefaultRepository(contentType)" dependency in ServicesController?

A: 

I've solved this problem by implementing method

_repository.GetSlugsForContentType(contentType, limit, q)

and creating a parameterless default constructor on XmlDefaultRepository implementation of IRepository.

This is the DI way of solving this issue with a Repository factory.

// ServicesController.cs
// ninject factory example, see IRepositoryFactory interface and its XmlRepositoryFactory implementation 
[Inject]
public IRepositoryFactory RepositoryFactory
{
set
{
factory = value;
}
}

private IRepositoryFactory factory;

public ActionResult ContentSlugsThruFactory(string contentType, string q, int limit)
{
    IRepository _repository = factory.Create(contentType);
    return Json(_repository.GetSlugsForContentType(limit, q), JsonRequestBehavior.AllowGet);
}

// IRepositoryFactory.cs
public interface IRepositoryFactory 
{ 
    IRepository Create(string contentType); 
} 

// XmlRepositoryFactory.cs
public class XmlRepositoryFactory : IRepositoryFactory
{
    public IRepository Create(string contentType)
    {
        return XmlDefaultRepository.Create(contentType);
    }
}

// XmlDefaultRepository.cs
public static XmlDefaultRepository Create(ContentType contentType)
{
    return new XmlDefaultRepository(contentType);
}

public static XmlDefaultRepository Create(string contentType)
{
    return new XmlDefaultRepository(contentType);
}

// global.asax.cs
Bind<IRepositoryFactory>().To<XmlRepositoryFactory>().InSingletonScope();
mare