Asp.net mvc 4 访问简单喷油器MVC视图的容器

Asp.net mvc 4 访问简单喷油器MVC视图的容器,asp.net-mvc-4,dependency-injection,sitecore,inversion-of-control,simple-injector,Asp.net Mvc 4,Dependency Injection,Sitecore,Inversion Of Control,Simple Injector,在一个Sitecore项目中,我使用 它使用sitecore管道,然后使用App_start中的方法 namespace BBC.App_Start { public class SimpleInjector : IPackage { public void RegisterServices(Container container) { GetContainer.RegisterServices(container);

在一个Sitecore项目中,我使用

它使用sitecore管道,然后使用App_start中的方法

namespace BBC.App_Start
{
    public class SimpleInjector : IPackage
    {
        public void RegisterServices(Container container)
        {
            GetContainer.RegisterServices(container);

            container.Register(() => new SitecoreContext(), Lifestyle.Scoped);
            container.Register(() => new Container(), Lifestyle.Singleton);
        }
    }
}
简单地说,我可以将容器注入控制器构造函数,但不能在视图文件中包含容器

我试图在appstart中声明一个静态属性,并将容器保存到其中。但我仍然没有在视图中获得注册类型

在视图中使用容器对象的最佳方式是什么?

正如他在评论中所建议的那样,您的问题的字面答案是“您不应该这样做,因为MVC和DI实际上不是这样工作的”。更详细的答案如下:

public class MyModel
{
    public string SpecialData { get; set; }
}

public class MyController : Controller
{
    public ActionResult DoSomething()
    {
        // do whatever processing is needed
        var somethingCalculate = resultFromYourOtherObject();
        // do other stuff

        var model = new MyModel() { SpecialData = somethingCalculated };

        return View(model);
    }
}
视图的任务是显示通过模型传递的数据。视图不应该真正包含逻辑。非常简单的东西,如“如果标志为false,则隐藏此标记块”是可以的,但用于计算标志值的更复杂代码不应出现在视图中

MVC鼓励您将表示(视图)与数据(模型)和逻辑(控制器)分开,从而使我们的网站代码变得更好。这将使我们的代码更易于使用-因此,如果您有需要执行的处理,那么它应该在控制器方法运行时真正发生

如果视图需要一些特殊数据,最佳实践建议它应该在控制器方法中计算出来,并将其传递给模型中的视图。代码可能更像这样:

public class MyModel
{
    public string SpecialData { get; set; }
}

public class MyController : Controller
{
    public ActionResult DoSomething()
    {
        // do whatever processing is needed
        var somethingCalculate = resultFromYourOtherObject();
        // do other stuff

        var model = new MyModel() { SpecialData = somethingCalculated };

        return View(model);
    }
}
然后,视图只需要接受
MyModel
类作为其模型,并呈现
SpecialData
属性-不需要逻辑

我认为,让调用从DI容器获取对象散布在代码库中也是一个坏主意。对于MVC应用程序,通常在应用程序启动时,DI容器会连接到为请求创建控制器的过程中。DI框架扩展了控制器的创建过程,而不是将DI容器传递到控制器中,并且容器不会暴露于此之外。当MVC运行时需要创建控制器时,控制器创建逻辑使用DI框架获取所有控制器依赖项的对象

如果没有关于您实际想要实现什么的更多细节,很难说创建对象的“正确”方法是什么,但最常见的两种模式可能是:

1) 构造函数注入:您的控制器有一个接受所需对象的参数。DI容器在创建控制器的位置为您创建此对象,因此您的控制器在创建时获得其所有依赖项。适用于:您知道如何在请求开始时创建对象的场景

public interface IMySpecialObject
{
    string DoSomething();
}

public class MyController : Controller
{
    private IMySpecialObject _specialObject;

    public MyController(IMySpecialObject specialObject)
    {
        _specialObject = specialObject;
    }

    public ActionResult RenderAView()
    {
        // do some stuff
        var data = _specialObject.DoSomething();

        return View(data);
    }
}
只要在应用程序启动时将IMySpecialObject及其具体实现注册到DI容器中,一切都很好

2) 工厂类:但是,有时所讨论的对象可能是可选的,或者可能需要在控制器创建时不可用的数据来创建它。在这种情况下,DI框架可以将工厂对象传递给控制器,这将用于以后构建特殊对象

public interface ISpecialFactory
{
    ISpecialObject CreateSpecialObject(object data);
}

public class MyController : Controller
{
    private IMySpecialFactory _specialFactory;

    public MyController(IMySpecialFactory specialFactory)
    {
        _specialFactory = specialFactory;
    }

    public ActionResult RenderAView()
    {
        // do some stuff
        if( requireSpecialObject )
        {
            var data = getSomeData();
            var specialObject = _specialFactory.CreateSpecialObject(data);
            var data = _specialObject.DoSomething();
            return View(data);
        }

        return View("someOtherView");
    }
}

但是一本关于使用DI的好书可能会建议其他更适合您特定问题的方法。

您的视图中不应该有任何依赖项。视图应该是普通DTO,控制器(或其他组件)应该创建它们。也不应该将容器本身链接到类中;第三,你不应该注册(()=>newcontainer(),…)。这将注册一个空容器。