2016-09-30 5 views
0

Проблема заключается в том, что у меня есть проект из 3 слоев: DataAccess dll и Presentation dll зависит от Logic dll. В логике я определил интерфейсы IRepository, IMyIdentityUser и т. Д. В DataAccess я использую среду Microsoft Identity для регистрации новых пользователей с MyIdentityUser, которая наследует IdentityUser<Guid> и IMyIdentityUser. Я также использую контейнер IoC. Предположим, что у меня есть метод уровня представления (MVC), называемый «Register» с аргументом «RegisterViewModel viewModel», который делегирует регистрацию логики некоторому классу в dll Logic.Создание волатильных экземпляров интерфейсов - инжекция зависимостей против локатора службы

public async Task<ActionResult> Register(RegisterViewModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      var user = MyCore.Resolve<IMyIdentityUser>(); //this is service locator 
                  // antipattern and I want to get 
                  // rid of this 
      user.UserName = model.Email; 
      user.Email = model.Email; 


      var userManager = _userManager; 


      var result = await userManager.CreateAsync(user, model.Password); 
      if (result.Succeeded) 
      { 
       var signInManager = _signInManager; 

       await signInManager.SignInAsync(user, false, false); 
       return RedirectToAction("Index", "Home"); 
      } 
      AddErrors(result); 
     } 


     return View(model); 
    } 

как вы видите Я использую локатор сервисов для получения нового экземпляра MyIdentityUser. Я не хочу создавать это как «new MyIdentityUser()», потому что это заставляет меня использовать жесткую связь с dll DataAccess, где определен MyIdentityUser. Кроме того, я не хочу иметь в конструкторе параметр IMyIdentityUser и принудительно использовать контейнер IoC для создания нового экземпляра пользователя каждый раз при создании MVC-контроллера. Я думаю, что я мог бы использовать какое-то абстрактную фабрику как

interface IMyIdentityUserFactory 
{ 
    IMyIdentityUser CreateNewUser(string name, string email); //any other better arguments? 
     // not like registerViewModel because 
     // this view model should be defined in presentation logic 
} 

и передать его в качестве аргумента в контроллер конструктора (может быть, в параметре фасадного с другими логически связанными параметрами), но я не уверен в этом, потому что это вообще такой же, как проходящий одинокий IMyIdentityUser. Есть ли лучший способ сделать это?

ответ

3

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

Ваше помещение ошибочно с нуля.

  1. Контроллеры MVC не имеют состояния. Каждый запрос создает MVC-контроллер (ну, если вы читаете здесь пункт №2, вы можете утверждать, что можете изменить это поведение по умолчанию, если вы реализуете IControllerActivator!)
  2. Контейнеры IoC не обязательно создают новый экземпляр данной введенной зависимости: это зависит от жизненного цикла компонента. Например, Castle Windsor предоставит вам временные, однотонные, для каждого запроса, для потоков, объединенные и другие жизненные циклы. Переходный период будет единственным выбором, который, несомненно, создаст экземпляр данной инъекционной зависимости.

Таким образом, исходя из ваших неправильных предположений, я бы окончательно пошел с инъекцией конструктора там, где вам нужна зависимость. Или впрыск свойств, но это не первый выбор при внедрении инъекции зависимостей, потому что обычно вложения свойств опционально.

С другой стороны, внедрение конструкции должно быть способом, потому что каждый фрагмент кода будет независим от других (без связи) с точки зрения проверяемости: вы можете автоматически или вручную создавать экземпляр данного класса, а также автоматически или вручную обеспечить свои зависимости.

+0

A.D. 1. Да, они не имеют состояния.Поэтому, если у контроллера есть 4 метода, и только один из них нуждается в новом пользователе от конструктора, это будет пустой тратой ресурсов, чтобы позволить контейнеру IoC создавать этого пользователя каждый раз, когда мы используем оставшиеся 3 метода - при условии, что Пользователь имеет временный или индивидуальный жизненный цикл. Но он не может быть одноточечным или для потока, и объединение не имеет большого смысла. Лучше всего было бы создать этого пользователя ** только ** для метода Register. Конечно, новый Пользователь очень легкий объект и не будет сильно влиять на производительность приложения, но все же я хотел бы знать, как это сделать должным образом. –

+0

@ BartekWójcik Я собираюсь ответить вам на обновление! –

+0

@ BartekWójcik Хорошо, давайте обсудим это здесь, прежде чем добавлять обновление к моему ответу. –