Вопрос

Допустим, у меня есть объект пользователя, и я хотел бы установить свой свойство создания в конструкторе для DateTime.Now. Но будучи усыновлением модуля, я не хочу получить доступ к DateTime.Now напрямую, но используйте itimeProvider:

public class User {
    public User(ITimeProvider timeProvider) {
        // ...
        this.CreationTime = timeProvider.Now;
    }

    // .....
}

public interface ITimeProvider { 
    public DateTime Now { get; }
}

public class TimeProvider : ITimeProvider {
    public DateTime Now { get { return DateTime.Now; } }
}

Я использую Ninject 2 в моем приложении ASP.NET MVC 2.0. У меня есть церкви и два метода создания (один для получения и один для поста). Тот, который для получения прямо вперед, но тот, который для поста не так прямой, и не так продвинут: P, потому что мне нужно связываться с модельной связующим, чтобы сказать ему, чтобы получить ссылку на реализацию ItimeProvider, чтобы иметь возможность построить пользовательский экземпляр.

public class UserController : Controller {

    [HttpGet]
    public ViewResult Create() {
         return View();
    }

    [HttpPost]
    public ActionResult Create(User user) {

         // ...

    }
}

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

Любой шанс решить этот простой / элегантный / и т. Д.? : D.

Это было полезно?

Решение

Как насчет вместо того, чтобы использовать ITimeProvider попробуй это:

public class User 
{
    public Func<DateTime> DateTimeProvider = () => DateTime.Now;

    public User() 
    {
        this.CreationTime = DateTimeProvider();
    }
}

И в вашем модульном тесте:

var user = new User();
user.DateTimeProvider = () => new DateTime(2010, 5, 24);

Я знаю, что это не очень элегантно, но вместо того, чтобы возиться с модельным связующим, это может быть решение. Если это не похоже на хорошее решение, вы могли бы реализовать пользовательскую модель Binder и переопределять CreateModel. Способ, где вы ввели зависимости в конструкторе модели.

Другие советы

Пара наблюдений:

Не вводите зависимости, чтобы запрашивать их в конструкторе

Нет никаких оснований ввести ITimeProvider в пользователь, просто чтобы вызвать Now немедленно. Просто введите время создания напрямую:

public User(DateTime creationTime)
{
     this.CreationTime = creationTime;
}

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

Не используйте ди с ModelBinders

ASP.NET MVC ModelBinder - это действительно плохое место, чтобы сделать ди, особенно потому, что вы не можете использовать инъекцию конструктора. Единственный оставшийся вариант Статический сервисный локатор анти-образцы.

ModelBinder переводит информацию HTTP Get и публиковать информацию на сильно напечатанный объект, но концептуально Эти типы не являются объектами домена, но похожие на Объекты передачи данных.

Гораздо лучшее решение для ASP.NET MVC - отказаться полностью и вместо этого Явно обнимаю что то, что вы получаете от HTTP-соединения, не ваш полный объект домена.

Вы можете иметь простой поиск или Mapper для получения объекта вашего домена в вашем контроллере:

public ActionResult Create(UserPostModel userPost)
{
    User u = this.userRepository.Lookup(userPost);
    // ...
}

куда this.userRepository является инъекционной зависимостью.

Другой вариант состоит в том, чтобы создать другой класс для представления пользователей, которые еще не были сохранены, что не имеет свойств даты создания вообще.

Даже если CreationDate один из UserИнварианты, его можно оттудаваться в модели вашего просмотра - и вы можете установить его дальше вниз по течению, в вашем контроллере или доменном слое.

В конце концов, это, вероятно, не имеет значения, но если атрибут даты создания действительно представляет момент, когда вы построить пользовательский экземпляр, Или это будет более подходящим для него представлять момент, когда пользователь подает свои данные?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top