2013-09-07 2 views
1

Я «новый» при использовании Injection Dependency, и мой вопрос: где я могу использовать оператор new? В следующем примере я покажу вам пример, и мне нравится знать, правильно ли я использую оператор new.Зависимость Инъекция, где использовать «новый» Оператор

Пример для ASP.NET MVC с CustomControllerFactory, все работает до сих пор.

Сначала я Мой Entity Класс Member:

public partial class Member 
{ 
    public Member() 
    { 
     this.LoginTries = 0; 
    } 

    public int Id { get; set; } 
    public string Username { get; set; } 
    public string Password { get; set; } 
    public DateTime CreationDate { get; set; } 
    public int LoginTries { get; set; } 
} 

Тогда есть интерфейс для некоторых действий пользователя:

public interface IDiMembership<TUser> 
{ 
    bool Login(string username, string password, bool rememberMe = false); 
    void Logout(); 
    //This is the Function I am using later and where i am using the new Operator 
    bool CreateUser(string username, string password, TUser user); 
    ... 
} 

Моя реализация для моего интерфейса:

public class DiMembership : IDiMembership<Member> 
{ 
    ... 
    public bool CreateUser(string username, string password, Member user) 
    { 
     user.PasswordSalt = Crypto.GenerateSalt(); 
     user.Password = Crypto.HashPassword(
      string.Format("{0}{1}", password, user.PasswordSalt)); 
     user.Username = username; 
     user.CreationDate = DateTime.Now; 
     ... 
    } 

И мой звонок Controller, и вот мой вопрос: правильно позвонить CreateUser с новым «членом» или для создания нового объекта Member префикс некоторые значения? Соответствует ли это DI или как правильно решить проблему?

private readonly IDiMembership<Member> _membership; 
public AccountController(IDiMembership<Member> membership) 
{ 
     _membership = membership; 
} 

public ActionResult Register(RegisterModel model) 
{ 
    if (ModelState.IsValid && 
     _membership.CreateUser(model.Username, model.Password, new Member())) 
    { 
     return RedirectToAction("RegisterSuccess"); 
    } 
    ... 
} 
+0

Читайте это: [К «новому» или не к «новому»] (http://misko.hevery.com/2008/09/30/to-new-or-not-to-new/). – Steven

ответ

1

Я бы посоветовал следующий подход:

  • сложных объекты (те, требующие некоторую бизнес-логику или сложный процесс инициализации) должно быть создан с помощью фабрики
  • нехитрых объектов (. Например DTO или POCO) могут быть созданы в любом месте

Если ваш RegisterModel хранит только несколько простых значений, нет смысла делегировать его создание на заводе, поскольку оно слишком растянуто создание ненужных классов.

Вы используете завод для string, int или DateTime? Нет. Но как только эти простые значения повысятся до некоторого более высокого уровня сложности или придут к какой-то бизнес-логике, мы перейдем от к новинкам к выделенным объектам для создания - подумайте о StringBuilder или Random.

1

Некоторые структуры DI обеспечивают фабрики для этой цели, так что вы никогда не будете нужно позвонить оператору new. Например, замок Виндзор предоставляет Typed factories.

При этом, вы бы просто определить интерфейс:

public interface IUserFactory 
{ 
    public IUser CreateUser(string username, string password...); 
} 

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

public class User : IUser 
{ 
    public User(string username, string password ...) 
    { 

    } 

} 

Логически, контроллер также должен объявить этот завод как зависимость ,

public class AccountController 
{ 
    private IUserFactory _userFactory; 

    public AccountController(IUserFactory userFactory) 
    { 
    _userFactory = userFactory; 
    } 

    public ActionResult Register(RegisterModel model) 
    { 
    IUser user = _userFactory.CreateUser(model.Username, model.Password); 
    ... 
    } 
} 

Если, однако, вы не используете рамки, или ваша база не обеспечивает фабричные реализации, то вы можете написать свои собственные заводы, которые содержат ссылку на контейнер компонентов и способны решить IUser, когда вы вызываете их методы Create.

Таким образом, вам не нужно будет звонить оператору new, чтобы создать новые объекты как часть логики вашего контроллера.

+0

Мне всегда нравился этот шаблон. Он изолирует построение динамических объектов в одном месте в вашем приложении. Поскольку фабрики создают даже самые простые объекты, вы можете наделить ваши объекты более широким набором обязанностей, уменьшить использование геттеров/сеттеров и сделать более понятными определения фактических зависимостей класса. Интересно, знаете ли вы, кто создал приложение с НЕТ новых операторов (помимо корня композиции)? Я всегда хотел попробовать, но дополнительная инфраструктура (по крайней мере, вдвое превышает количество классов) делает ее нецелесообразной для реализации, я нахожу по крайней мере. – jrahhali

+0

@jrahhali, теперь я открываю образец DI и просматриваю всю сеть, ища ответ на вопрос, который вы ставите: как создать фабрики - классы, чья ответственность заключается в создании других объектов на основе некоторых вычислений времени выполнения, а не нарушить принцип DI: не использовать «новый» оператор и напрямую обращаться к контроллеру DI. Мне кажется, что правильный ответ: –

+0

тот, который вы предложили: создать заводы даже для простейших объектов. BTW, в PHP (в котором я пишу) позволяет создавать анонимные классы, такие как замыкания: $ myFactory = новый класс ($ container) {// здесь определяется определение класса} это позволяет не удваивать число классов –

Смежные вопросы