谁在创建_Layout.cshtml

时间:2012-01-17 11:53:04

标签: .net asp.net-mvc dependency-injection castle-windsor

我在Windsor中使用IDependencyResolver实现,其自定义WebViewPage在MVC3项目中都具有服务作为属性(假定日志服务)。

服务注入所有视图(它们的创建通过IDependencyResolver)。

问题是在_Layout.cshtml(布局)中,服务保持为空。

所以问题是谁在创建布局,因为它不是由IDependencyResolver创建的(或者我可能只是错过了明显的)?

修改

public abstract class WebViewPage<TModel> : System.Web.Mvc.WebViewPage<TModel>
{
    public ILocalizer Localizer { get; set; }
}

然后

<pages pageBaseType="[full namespace].WebViewPage">
来自〜/ Views的web.config中的system.web.webPages.razor和system.web部分中的

最后依赖解析器:

public class WindsorDependencyResolver : IDependencyResolver
{
    private readonly IKernel kernel;

    public WindsorDependencyResolver(IKernel kernel)
    {
        this.kernel = kernel;
    }

    public object GetService(Type serviceType)
    {
        return kernel.HasComponent(serviceType) ? kernel.Resolve(serviceType) : RegisterAndResolve(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return kernel.HasComponent(serviceType) ? kernel.ResolveAll(serviceType).Cast<object>() : new object[] { };
    }

    private object RegisterAndResolve(Type serviceType)
    {
        if (!serviceType.IsAbstract && !serviceType.IsInterface)
        {
            kernel.Register(Component.For(serviceType).ImplementedBy(serviceType).LifestylePerWebRequest());
            return kernel.Resolve(serviceType);
        }
        return null;
    }
}

依赖项解析程序在Global.asax.cs中设置:

var dependencyResolver = new WindsorDependencyResolver(container.Kernel);
DependencyResolver.SetResolver(dependencyResolver);

当实例化任何视图(Index.cshtml)时,将调用依赖项解析程序中的GetService方法,并由容器创建视图。对于_Layout.cshtml,该方法未被调用。

所以当我在Index.cshtml中执行此操作时:@Localizer.Localize(....) localizaer服务不为null,但在_Layout.cshtml中它是null,具体问题是我无法在视图中本地化任何内容(我不希望每个支持的语言环境都有一个视图)。

我希望现在更清楚了。

修改 关于这一个仍然没有明确答案...... 我没有时间检查MVC来源,但肯定答案肯定在那里......

1 个答案:

答案 0 :(得分:1)

它是由Razor视图引擎创建的。它的基类型是在~/views/web.config节点的pageBaseType属性的pages内定义的。默认情况下为System.Web.Mvc.WebViewPage

如果您想在Razor模板中进行依赖注入(无论是_Layout还是其他视图),您可以定义自定义页面基本类型:

public abstract class MyWebViewPage<T> : WebViewPage<T>
{
    public MyWebViewPage()
    {
        SomeDependency = DependencyResolver.Current.GetService<IFoo>();
    }

    public IFoo SomeDependency { get; private set; }
}

然后在~/views/web.config中设置基本类型:

<pages pageBaseType="AppName.Controllers.MyWebViewPage">

然后所有模板都将提供SomeDependency属性:

@model MyViewModel
@SomeDependency.FooBar()

请注意,在某些情况下,这可能不是一个好的设计选择。如果您打算向视图注入一些自定义HTML帮助器,那么就可以了。但是,如果您打算注入一些域服务并让您的视图开始从左侧和右侧获取依赖项而不是使用视图模型,那么您正在犯一个严重的设计错误,因为视图的责任不是获取依赖项。它的职责是以视图模型的形式显示它传递的信息。此信息来自哪里不是视图责任。它是控制器,用于协调获取数据并将其放入传递给视图的视图模型中。