我正在为我的控制器创建一个自定义ActionResult
,因为我注意到很多可以重复使用的重复代码。它看起来像这样:
public ExtendedViewResult<T> : ActionResult
{
protected T Model { get; set; }
protected IModelExtender<T> Extender { get; set; }
public ExtendedActionResult(T model, IModelExtender<T> extender)
{
this.Model = model;
this.Extender = extender;
}
}
public class BaseController : Controller
{
public ExtendedViewResult<T> ExtendedView<T>(T model)
{
// I need to create the result here, but how?
var result = new ExtendedViewResult<T>(model, ???????);
return result;
}
}
我遇到的问题是我不确定如何构造我的ExtendedViewResult对象。由于接口是通用的,我想使用依赖注入来获取正确的对象,但我不知道如何做到这一点,因为我自己构建对象。
我正在使用Ninject和Ninject.MVC3,默认的Nuget包为我创建了一个Bootstrapper类,当我访问Bootstrapper.Kernel属性时,我收到以下警告:
Ninject.Web.Mvc.Bootstrapper.Kernel is obsolete. Do not use Ninject as Service Locator.
如果我不应该直接访问内核,那么如何更改代码以便我可以获得适当的具体类?
修改
这是ninject引导程序代码。我添加的唯一方法是GetInstance()
public static class NinjectMVC3
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestModule));
DynamicModuleUtility.RegisterModule(typeof(HttpApplicationInitializationModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
// I ADDED THIS CODE, EVERYTHING ELSE IS AUTO-GENERATED
// BY THE NUGET PACKAGE
public static T GetInstance<T>()
{
return bootstrapper.Kernel.Get<T>();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
}
}
答案 0 :(得分:1)
很抱歉这对于实际代码来说会很干 - 我没有使用ninject,但是其他DI容器都有这个解决方案,我相信ninject也会有这个构造。
问题是你正在构建对象本身。当你真正使用DI容器并关注IoC时,只要你看到关键字new
应该是一个红色标志 - 并且使用容器作为服务定位器是黄色的。
那么我们如何摆脱'新',因为你需要一个新的对象?答案是让您的BaseController
依赖可以创建ExtendedViewResult
的工厂。在Autofac(我选择的容器)中,这就像注入Func<ExtendedViewResult>
一样简单。如果Ninject没有相同的话,我会感到惊讶。事实上,它看起来像 - this ninject wiki page指向此blog post on Ninject.Extensions.Factory。
这意味着您的Controller代码可能如下所示:
public class ConcreteController : BaseController
{
private Func<Foo,ExtendedViewResult<Foo>> _factory;
public BaseController(Func<Foo,ExtendedViewResult<Foo>> factory)
{
_factory = factory;
}
public ExtendedViewResult<Foo> Method(Foo model)
{
var result = _factory(model);
return result;
}
}
如果你真的想要一个通用的方法在基类中进行创建,那么你可能需要从上面链接的博客文章中去显式工厂界面路径。但是,使用这种样式代码,在大多数情况下您不需要它,并且您的控制器显式声明了它们所需的依赖项。
答案 1 :(得分:0)
当您的对象想要创建其他对象时,您应该使用抽象工厂。抽象工厂本身可以注入。我在这里问了一个类似的问题:Abstract factories when using dependency injection frameworks
尽管你的工厂是通用的,但实际上并没有太大区别。