最佳实践 - 如何从控制器工厂取回内部绑定?

时间:2012-11-14 22:31:25

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

我正在关注史蒂文桑德森和亚当弗里曼的“ASP.Net MVC 3”,他们一度定义ControllerFactory。暴露的接口用于创建控制器,注入它们的内容(如提供数据的类)是黑盒子(用于外部世界)。

我就是这样,我真的不想得到任何控制器,而是控制器的绑定集 - 即提供数据的类。

我可以为控制器工厂添加另一种方法(例如GetBinding)并且它可以工作,但它是正确的方式吗?


专注于某事。我有IDataProvider和两个班级 - MockupProviderProviderForReal。我想设置一次,现在只要我需要IDataProvider,我就会得到MockupProvider。这是由(我)在控制器工厂设置的。

我想以大多数优雅的方式检索我设置的内容,因此我不会再次绑定接口类。添加这样的方法 - GetBinding - 对控制器因素是一个好的模式吗?

我没有构建控制器,我需要使用绑定控制器。


换句话说......

有控制器工厂。里面有定义了一些绑定。我必须使用检索它们(绑定,而不是控制器)。从技术上讲,我可以通过几种方式做到这一点:

  • 看看代码,查看特定的绑定,并在其他地方使用绑定类型(硬编码)

  • 将公共方法添加到控制器工厂GetBinding

  • ...

什么是正确的方法?


更新

我的控制器工厂:

public class NinjectControllerFactory : DefaultControllerFactory
{
    private IKernel ninject_kernel;

    public NinjectControllerFactory()
    {
        ninject_kernel = new StandardKernel();
        AddBindings();
    }

    private void AddBindings()
    {
        ninject_kernel.Bind<IBookRepository>().To<DataManagement.Concrete.EFBookRepository>();
        // ninject_kernel.Bind<IBookRepository>().ToConstant(DataManagement.Mocks.Mocks.BookRepository);
    }

    public T GetBinding<T>()
    {
        return ninject_kernel.Get<T>();
    }

    protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null)
            return null;
        else
            return (IController)ninject_kernel.Get(controllerType);
    }
}

1 个答案:

答案 0 :(得分:1)

我正在尝试在评论后回答您的问题。如果它不适合你,我准备删除它。

所以在我的ASP.NET MVC应用程序中,我正在使用ninject及其mvc扩展来为我的控制器(以及底层服务和存储库)注入依赖项。

<强> Global.asax中

public class MvcApplication : Ninject.Web.Mvc.NinjectHttpApplication
{
        /// this is here only to see that NinjectHttpApplication uses its own ControllerFactory, which is supposed to create your controllers with dependencies injected
        protected override Ninject.Web.Mvc.NinjectControllerFactory CreateControllerFactory()
        {
            return base.CreateControllerFactory();
        }

        protected override IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            // here you can configure your bindings according to actual requirements 
            kernel.Bind<IDataProvider>().To<ProviderForReal>().InRequestScope(); 
            kernel.Bind<IDataService>().To<RealDataService().InRequestScope();                
            return kernel;
        }
}

<强>控制器

public class MyController : Controller
{
    private readonly IDataProvider dataService;
    // i will get injected an IDataProvider according to my actual configuration
    public MyController(IDataService dataService)
    {
          this.dataService = dataService;
    }
}

<强> IDataService

public class RealDataService: IDataService{
     private readonly IDataProvider dataProvider;
     public RealDataService(IDataProvider dataProvider){
         this.dataProvider = dataProvider;
     } 
}

更新

您无需编写自己的控制器工厂。在上面的代码中,我将CreateControllerFactory方法的覆盖仅用于显示Ninject.Web.Mvc.NinjectHttpApplication隐式覆盖此方法并使用其自己的NinjectControllerFactory implmentation,它将为您解析依赖项(即使该依赖项是间接的 - 你可以在我更新的代码中看到=&gt; Ninject会为你解决它,因为它会看到MyController需要IDataService并且会查看绑定并且会看到绑定到{ {1}},但它只有依赖于RealDataService的构造函数。所以它会再次查看绑定,并且会看到IDataProvider绑定到IDataProvider而不是创建ProviderForReal将它注入ProviderForReal而不是RealDataService注入ReadDataService)。