ASP.NET MVC和StructureMap的最佳实践DI - 如何在ActionResult中注入依赖项
我编辑了我的整个问题,所以不要怀疑:)
好吧,我想要一个带有域模型数据和一些附加参数的
ActionResult
,即用于分页列表的页面索引和页面大小。它决定自己是否返回PartialViewResult或ViewResult,具体取决于Web请求的类型(ajax请求与否)。
应使用IMappingService自动映射引用的数据,IMappingService负责将任何域模型数据转换为视图模型。
为了简单起见,MappingService使用AutoMapper。
MappingActionResult:
public abstract class MappingActionResult : ActionResult
{
public static IMappingService MappingService;
}
BaseHybridViewResult:
public abstract class BaseHybridViewResult : MappingActionResult
{
public const string defaultViewName = "Grid";
public string ViewNameForAjaxRequest { get; set; }
public object ViewModel { get; set; }
public override void ExecuteResult(ControllerContext context)
{
if (context == null) throw new ArgumentNullException("context");
var usePartial = ShouldUsePartial(context);
ActionResult res = GetInnerViewResult(usePartial);
res.ExecuteResult(context);
}
private ActionResult GetInnerViewResult(bool usePartial)
{
ViewDataDictionary viewDataDictionary = new ViewDataDictionary(ViewModel);
if (String.IsNullOrEmpty(ViewNameForAjaxRequest))
{
ViewNameForAjaxRequest = defaultViewName;
}
if (usePartial)
{
return new PartialViewResult { ViewData = viewDataDictionary, ViewName = ViewNameForAjaxRequest };
}
return new ViewResult { ViewData = viewDataDictionary };
}
private static bool ShouldUsePartial(ControllerContext context)
{
return context.HttpContext.Request.IsAjaxRequest();
}
}
AutoMappedHybridViewResult:
public class AutoMappedHybridViewResult<TSourceElement, TDestinationElement> : BaseHybridViewResult
{
public AutoMappedHybridViewResult(PagedList<TSourceElement> pagedList)
{
ViewModel = MappingService.MapToViewModelPagedList<TSourceElement, TDestinationElement>(pagedList);
}
public AutoMappedHybridViewResult(PagedList<TSourceElement> pagedList, string viewNameForAjaxRequest)
{
ViewNameForAjaxRequest = viewNameForAjaxRequest;
ViewModel = MappingService.MapToViewModelPagedList<TSourceElement, TDestinationElement>(pagedList);
}
public AutoMappedHybridViewResult(TSourceElement model)
{
ViewModel = MappingService.Map<TSourceElement, TDestinationElement>(model);
}
public AutoMappedHybridViewResult(TSourceElement model, string viewNameForAjaxRequest)
{
ViewNameForAjaxRequest = viewNameForAjaxRequest;
ViewModel = MappingService.Map<TSourceElement, TDestinationElement>(model);
}
}
控制器中的用法:
public ActionResult Index(int page = 1)
{
return new AutoMappedHybridViewResult<TeamEmployee, TeamEmployeeForm>(_teamEmployeeRepository.GetPagedEmployees(page, PageSize));
}
所以你可以看到IMappingService
是隐藏的。当使用AutoMappedHybridViewResult
时,控制器不应该对IMappingService
接口有任何了解。
MappingActionResult
与static IMappingServer
是否合适,还是我违反了DI原则?
没有找到相关结果
已邀请:
2 个回复
姬第柔炒
实现是这样的(您需要为每个HybridViewResult构造函数创建重载):
这样您就可以从控制器中隐藏实现,而不必依赖容器。
亲奋漏
等等 我不确定为什么你需要使用ActionResult,但如果没有理由明确需要它,你可以创建一个HybridViewModel类和一个注入了映射服务依赖项的HybridViewModelBinder类。 我假设您想要使用构造函数注入,但如果您在UI程序集中具有StructureMap依赖项,则可以访问静态依赖项解析程序类(如Clowers所述)。 如果我明白你使用ActionResult的原因,这个问题会更容易给出明确的答案。 您似乎正在使用操作结果来处理两个功能,这些功能不一定总是在一起,并且可以单独使用。此外,没有明确的迹象表明它需要在ActionResult中。 据推测,您可以(a)利用Automapper功能获得除html(ViewResult)输出之外的其他结果,以及(b)您可以利用自动检测Ajax请求的功能,而无需自动化模型。 在我看来,可以使用视图模型的自动化将视图模型直接注入控制器操作,从而消除控制器对IMappingService的依赖性。您需要的是一个要注入IMappingService的ModelBinder类(我假设其实现包含存储库或数据存储区类型依赖项)。 这是一篇很好的文章,解释了如何利用模型绑定器:http://odetocode.com/blogs/scott/archive/2009/04/27/6-tips-for-asp-net-mvc-model-binding.aspx。 然后,您可以覆盖需要自动执行的类中的DefaultModelBinder,如下所示:
现在,关于HybridViewResult,我建议您使用Action Filter来处理它。因此,您可以使用ActionResult或ViewResultBase作为操作方法的Result类型,并使用动作过滤器对其进行装饰,即:
我认为总的来说这比将这两个功能与ActionResult结合起来要好得多。