我正在创建一个内部应用程序框架,我们组织中的其他开发团队将使用它来构建 MVC 应用程序。作为其中的一部分,我正在为所有视图创建菜单结构,该结构是从配置中读取并根据当前用户的权限进行修改的。为了将菜单创建为框架的一部分,我创建了一个自定义WebViewPage
使用自定义 HTML Helper 类实现,该类需要依赖于ApplicationDataReader
构建菜单。
我读过各种文章,解释 MVC 需要WebViewPage
有一个无参数构造函数,所以我需要使用属性注入。我已经配置了Autofac MVC3 集成 http://code.google.com/p/autofac/wiki/MvcIntegration3,包括注册一个ViewRegistrationSource
。问题是,当访问依赖属性时,它始终为空。
这是自定义视图页面和我试图拨打的电话的帮助程序:
public abstract class OuBaseViewPage<TModel> : WebViewPage<TModel> where TModel : class
{
public OuHelper<TModel> Ou { get; set; }
public override void InitHelpers()
{
base.InitHelpers();
Ou = new OuHelper<TModel>(ViewContext, this);
}
}
public class OuHelper<TModel> where TModel : class
{
public OuHelper(ViewContext viewContext, IViewDataContainer viewDataContainer)
: this(viewContext, viewDataContainer, RouteTable.Routes)
{
}
public OuHelper(ViewContext viewContext, IViewDataContainer viewDataContainer, RouteCollection routeCollection)
{
ViewContext = viewContext;
ViewData = new ViewDataDictionary<TModel>(viewDataContainer.ViewData);
}
public ViewDataDictionary<TModel> ViewData { get; private set; }
public ViewContext ViewContext { get; private set; }
public IList<BusinessFocusArea> ReadFocusAreas()
{
// this is null - yes, service location, but an isolated instance of...
return DependencyResolver.Current.GetService<IDataReader>().Read();
}
}
问题源于这样一个事实:InitHelpers
正在被调用(通过Layout.Execute()
) 前Application_Start
被调用,因此没有注册任何依赖项。我知道将逻辑注入视图并不是一个好的做法,并且视图应该是愚蠢的,但这是一个应用程序框架,它需要执行使用该框架的开发人员不能看到的某些设置步骤。
我可以遵循更好的方法吗?
这里有一个类似的问题:Autofac 可以将依赖项注入布局视图文件吗? https://stackoverflow.com/questions/11593580/can-autofac-inject-dependencies-into-layout-view-files
问题源于 InitHelpers 被调用这一事实(通过
Layout.Execute()) 在调用 Application_Start 之前
我不认为之前有什么东西被调用过Application_Start
。我无法重现你的问题。
以下是我所做的步骤,效果非常好:
- 使用 Internet 模板创建新的 ASP.NET MVC 3 应用程序
- 安装
Autofac.Mvc3
NuGet
-
定义一个虚拟接口:
public interface IDataReader
{
}
-
还有一个虚拟实现:
public class DataReader : IDataReader
{
}
-
定义一个自定义助手:
public class OuHelper<TModel> where TModel : class
{
private readonly IDataReader dataReader;
public OuHelper(ViewContext viewContext, IViewDataContainer viewDataContainer, IDataReader dataReader)
: this(viewContext, viewDataContainer, RouteTable.Routes, dataReader)
{
}
public OuHelper(ViewContext viewContext, IViewDataContainer viewDataContainer, RouteCollection routeCollection, IDataReader dataReader)
{
ViewContext = viewContext;
ViewData = new ViewDataDictionary<TModel>(viewDataContainer.ViewData);
this.dataReader = dataReader;
}
public ViewDataDictionary<TModel> ViewData { get; private set; }
public ViewContext ViewContext { get; private set; }
public IDataReader DataReader
{
get { return this.dataReader; }
}
}
-
使用此帮助器定义自定义 WebViewPage:
public abstract class OuBaseViewPage<TModel> : WebViewPage<TModel> where TModel : class
{
public OuHelper<TModel> Ou { get; set; }
public override void InitHelpers()
{
base.InitHelpers();
var dataReader = DependencyResolver.Current.GetService<IDataReader>();
Ou = new OuHelper<TModel>(ViewContext, this, dataReader);
}
}
-
将默认视图页面替换为自定义视图页面~/Views/web.config
:
<pages pageBaseType="MvcApplication1.OuBaseViewPage">
-
配置您的容器Application_Start
:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterType<DataReader>().As<IDataReader>();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
-
现在您可以愉快地在包括 _Layout 在内的所有视图中使用自定义助手,没有任何问题:
@Ou.DataReader.GetType()
当然,在这个例子中我刚刚暴露了IDataReader
依赖项作为公共属性来向您说明它总是会被注入并且永远不会为空。在您的特定代码中,您当然可以仅使用帮助程序内的私有只读字段来完成您的任务。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)