Ninject依赖注入ASP.NET MVC控制器,其中存储库类型仅在运行时知道

时间:2010-07-22 16:21:30

标签: asp.net-mvc dependency-injection ninject

我已经在我的ASP.NET MVC应用程序中使用Ninject设置了DI

            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,它本身没有默认类型 - 它只是一个从jQuery向消费者提供JSON数据(JSON操作)的控制器。

现在的样子:

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

如何摆脱ServicesController中的“new XmlDefaultRepository(contentType)”依赖关系?

1 个答案:

答案 0 :(得分:2)

我通过实现方法

解决了这个问题
_repository.GetSlugsForContentType(contentType, limit, q)

并在IRepository的XmlDefaultRepository实现上创建无参数的默认构造函数。

这是使用Repository工厂解决此问题的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();