Это правильное использование шаблона локатора сервиса в моем MVC 3 ModelBinder? - PullRequest
4 голосов
/ 14 октября 2011

У меня есть приложение ASP.NET MVC 3, и я использую Ninject для внедрения зависимостей в мои классы.

Действия на контроллерах передают ViewModels (не содержащие логику) в слой представления.

Когда форма HTTP POSTed, MVC 3 создает экземпляр ViewModel и связывает входящие данные POST со свойствами ViewModel. MVC 3 использует класс DefaultModelBinder для создания экземпляра и выполнения привязки.

Большинство моих моделей ViewModel имеют зависимость, которую я не хочу устанавливать для каждого отдельного метода контроллера (принцип DRY).

Поэтому я создал собственный подкласс DefaultModelBinder следующим образом:

using System;

using System.Web.Mvc;

namespace Application.Classes {

    public sealed class CustomModelBinder : DefaultModelBinder {

        private readonly IDependencyResolver DependencyResolver;

        public CustomModelBinder( IDependencyResolver dependencyResolver ) {

            DependencyResolver = dependencyResolver;

        }

        protected override object CreateModel( ControllerContext controllerContext , ModelBindingContext modelBindingContext , Type modelType ) {

            return DependencyResolver.GetService( modelType );

        }

    }

}

И я установил его для замены DefaultModelBinder следующим образом (в Global.asax.cs):

protected void Application_Start() {

    // ...

    ModelBinders.Binders.DefaultBinder = new CustomModelBinder( DependencyResolver.Current );

    // ...

}

Делая это, когда метод Controller получает ViewModel, он будет построен Ninject с использованием привязки, указанной в моем NinjectModule. ViewModel теперь получает свои зависимости, вставленные в его конструктор.

Это правильное использование шаблона локатора службы?

Разъяснение / ОБНОВЛЕНИЕ:

Ответы [ 3 ]

5 голосов
/ 14 октября 2011

Насколько я понимаю, у вас есть ViewModel, которая наследуется от ViewModelBase, чтобы предоставлять AccountInformation во всех представлениях, в которых зарегистрирован пользователь.

Если я полностью не понял, это моя точка зрения:
AccountInformation должна использоваться только для отображения. Так что это не должно быть проблемой, когда ModelBinder по умолчанию не создает его, когда происходит публикация вашего действия. Я рекомендую вам снова получить AccountInformation с использованием, например, информации, которой вы располагаете. Controller.User и ваша база данных. Страница регистрации / профиля - это единственное место, где вы хотите, чтобы эта информация поступала из переменных POST. При необходимости вы можете кэшировать эту информацию для каждого пользователя.

Как я сказал в комментариях, ViewModels должны быть настолько глупыми, насколько это возможно. Они должны содержать только свойства с их типами и метаданными относительно проверки и т. Д.

Вся логика, которую вы хотите поместить в представление, поступает в контроллер.

Итак, в заключение; Не должно быть необходимости использовать Service Locator в ModelBinder.

2 голосов
/ 15 октября 2011

Просмотр моделей не должен иметь зависимостей.Это просто тупые контейнеры данных без функциональности.Вместо этого используйте фильтры для сквозных задач.

0 голосов
/ 14 октября 2011

вы рассматривали возможность использования Ninject для MVC3? Вы можете скачать его с здесь

Затем в вашем global.asax наследуются от NinjectHttpApplication:

public class MvcApplication : NinjectHttpApplication
{

Создать метод для переопределения ядра:

protected override IKernel CreateKernel()
{
   return new StandardKernel(new NinjectRepositoryModule(),
                             new NinjectAggregateServiceModule());
}

NijectRepositoryModule - это место, где я связываю свои интерфейсы с конкретными реализациями:

public class NinjectRepositoryModule: NinjectModule
{
        public override void Load()
        {
            Bind<IContactsRepository>().To<EFContactRepository>();
        }
}
...