Непосредственное внедрение зависимостей в контроллер ASP.NET MVC, где тип репозитория известен только во время выполнения - PullRequest
0 голосов
/ 22 июля 2010

Я настроил DI с помощью Ninject в своем приложении ASP.NET MVC, как это

            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 реализует IRepository и содержит конструктор, который принимает параметр contentType, который я использую для генерации пути персистентности.

Теперь у меня есть ServicesController, который сам по себе не имеет тип по умолчанию - это просто контроллер, который предоставляет данные JSON (действия JSON) потребителям из jQuery.

Вот как это выглядит сейчас:

    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);
        }
}

А вот так выглядят другие контроллеры (DI выполняется через инжектор конструктора):

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

Как мне избавиться от зависимости "new XmlDefaultRepository (contentType)" в ServicesController?

1 Ответ

2 голосов
/ 22 июля 2010

Я решил эту проблему, реализовав метод

_repository.GetSlugsForContentType(contentType, limit, q)

и создав конструктор по умолчанию без параметров в реализации XmlDefaultRepository IRepository.

Это способ DI для решения этой проблемы с помощьюРепозиторий фабрики.

// 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();
...