HtmlHelper создание выпадающего списка, используя ServiceLocator: запах кода? - PullRequest
2 голосов
/ 05 августа 2010

Является ли запах кода следствием следующего паттерна, учитывая следующий код (очень упрощенный, чтобы сразу перейти к сути)?

Модели:

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 ) %>

Шаблон редактора для категории

<% =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);
}

Для справки, для реальной реализации вспомогательного метода требуются лямбда-выражения, чтобы получить имена DataTextField и DataValueField, выбранное значение и т. Д.

Меня беспокоит использование сервис-локатора внутри HtmlHelper. Я думаю, что у меня должно быть свойство AllCategories в моей модели Product, но мне нужно будет заполнять его в контроллере каждый раз, когда мне это нужно.

Так что я думаю, что решение, которое я использую, является более простым, так как вспомогательный метод является универсальным (как и механизм связывания моделей, здесь не включенный). Поэтому мне просто нужно создать EditorTemplate для каждого типа, для которого требуется DropDownList.

Любой совет?

Ответы [ 2 ]

0 голосов
/ 06 августа 2010

ИМХО, я бы оставил все как есть, то же самое в другом проекте.

НО расположение службы меня тоже беспокоило, поэтому для другого проекта я сделал эту часть ActionFilter, которая сканирует модель, находит все ожидаемые выпадающие списки и выполняет пакетную загрузку в ViewData. Поскольку ServiceLocator или Repository / Context / что-либо уже введено в контроллер, вам не нужно распределять местоположение службы по всему месту.

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;
    }
}

В представлении вы можете затем создать помощника для загрузки этих выпадающих списков с помощью пользовательского шаблона редактора или другого метода.

0 голосов
/ 06 августа 2010

совет: посмотрите пример приложения asp.net mvc здесь: http://valueinjecter.codeplex.com/ удачи;)

Вот как пример приложения ValueInjecter может получить выпадающие списки: (но это не такПрямо сейчас, потому что я в порядке с вещью Решить)

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
                         });
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...