HtmlHelper使用ServiceLocator构建一个下拉列表:代码味道?

时间:2010-08-05 19:34:35

标签: asp.net-mvc service-locator

根据以下代码(高度简化以直接指向),是否需要遵循模式的代码气味?

模特:

class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Category Cat { get; set; }
}

class Category
{
    public int Id { get; set; }
    public string Label { get; set; }
}

编辑产品的视图:

<% =Html.EditorFor( x => x.Name ) %>
<% =Html.EditorFor( x => x.Category ) %>

类别的EditorTemplate

<% =Html.DropDownList<Category>() %>

HtmlHelper方法

public static MvcHtmlString DropDownList<TEntity>(this HtmlHelper helper)
    where TEntity : Entity
{
    var selectList = new SelectList(
        ServiceLocator.GetInstance<SomethingGivingMe<TEntity>>().GetAll(), 
        "Id", "Label");

    return SelectExtensions.DropDownList(helper, "List", selectList, null, null);
}

有关信息,helper方法的实际实现需要一些lambdas来获取DataTextField和DataValueField名称,选定的值等。

困扰我的一点是在HtmlHelper中使用servicelocator。我想我的产品模型中应该有一个AllCategories属性,但每次需要时我都需要在控制器中填充。

所以我认为我使用的解决方案更直接,因为辅助方法是通用的(模型绑定器也是如此,此处不包括在内)。所以我只需要为每个需要DropDownList的类型创建一个EditorTemplate。

有什么建议吗?

2 个答案:

答案 0 :(得分:0)

恕我直言,我会保持原样,在另一个项目中也有同样的事情。

但是服务位置也困扰着我,所以对于另一个项目我做了一个ActionFilter的一部分,它扫描模型,找到所有预期的下拉列表并批量加载到ViewData中。由于ServiceLocator或Repository / Context /已经注入Controller的任何内容,您不必在整个地方传播您的服务位置。

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
    foreach( var anticipated in SomeDetectionMethod() )
    {
          var selectList = new SelectList(
    ServiceLocator.GetInstance<SomethingGivingMe<TEntity>>().GetAll(), 
    "Id", "Label");

         ViewData["SelectList." + anticipated.Label/Name/Description"] = selectList;
    }
}

在视图中,您可以创建一个帮助程序,通过自定义编辑器模板或其他方法加载这些下拉列表。

答案 1 :(得分:-1)

建议:从这里查看asp.net mvc示例应用程序:http://valueinjecter.codeplex.com/ 祝你好运;)

这就是ValueInjecter的示例应用程序可以获得下拉列表的方式: (但它现在不是因为我对Resolve的事情没问题)

public class CountryToLookup : LoopValueInjection<Country, object>
{
    ICountryRepo _repo;

    public CountryToLookup(ICountryRepository repo)
    {
        _repo = repo;
    }

    protected override object SetValue(Country sourcePropertyValue)
    {
        var value = sourcePropertyValue ?? new Country();
        var countries = _repo.GetAll().ToArray();
        return
            countries.Select(
                o => new SelectListItem
                         {
                             Text = o.Name,
                             Value = o.Id.ToString(),
                             Selected = value.Id == o.Id
                         });
    }
}