más MVVM tendrían esta arquitectura:
View -> ViewModel -> Model -> Repository
Recientemente he sido abrazar una variante:
View -> ViewModel <- Presenter -> Model -> Repository
(Donde A -> B significa "A sabe sobre B", pero B no sabe acerca de A.)
Observe que en ambos casos, lo único que conoce sobre el repositorio es el modelo, no el modelo de vista. Su modelo no es solo las entidades de dominio, sino que también debe albergar la lógica comercial. Obviamente uno de los casos de uso de su lógica de negocio tiene que soportar es algo que llamaré una MemberEditTask
:
public class MemberEditTask
{
private readonly Member _member;
public MemberEditTask(Member member, IRepository repository)
{
this._member = member;
this.StatusChoices = repository.GetPossibleMemberStatuses(member);
}
public ReadOnlyCollection<MemberStatus> StatusChoices { get; private set; }
public MemberStatus Status
{
get { return this._member.Status; }
set
{
if(!this.StatusChoices.Contains(value))
{
throw new ArgumentOutOfRangeException();
}
this._member.Status = value;
}
}
}
Todo esto pertenece lógica en su modelo debido a que la lista de posibles opciones (y validar que una de ellas era realmente elegido) se define por lógica de negocios. También podría imaginarse algo más que consuma el MemberEditTask
, como un proceso automatizado que se ejecuta en el servidor que edita un miembro en respuesta a un archivo cargado en un servidor FTP o un proceso en segundo plano (estableciendo el estado en Inactivo después de una cierta cantidad de tiempo) Todas estas cosas necesitan ejecutar las mismas reglas de negocio, por lo que todo tiene que ser común (no en ViewModel).
Por lo tanto, dado que la clase, la clase ViewModel es así:
public class MemberEditViewModel : ViewModelBase
{
private readonly MemberEditTask _task;
public MemberEditViewModel(MemberEditTask task)
{
this._task = task;
}
public IEnumerable<MemberStatus> StatusChoices
{ get { return this._task.StatusChoices; }
public MemberStatus Status
{
get { return this._task.Status; }
set
{
this._task.Status = value;
NotifyAllPropertiesChanged();
}
}
}
En este caso, como muy simple conveniencia, simplemente creen que NotifyAllPropertiesChanged
es un método protegido de ViewModelBase
que utiliza la reflexión para criar a un PropertyChanged
evento en todos propiedades públicas de ViewModel. :) Eso es exagerado, por supuesto, pero conduce en un punto más importante ...
Esto es casi un ejemplo tonto porque en este caso, MemberEditViewModel
es innecesario. Si la Vista es la única configuración Status
, ¡entonces realmente no es necesario elevar el evento de cambio de propiedad! Por supuesto, en el mundo real, tendrá más propiedades y habrá interacciones. La razón por la que ViewModel existe es notificar a los consumidores cuando cambian sus propiedades relacionadas con la vista, que es algo que el Modelo no hace (y no debería, en mi opinión). (El ViewModel también tiene una lógica específica de Vista adicional para admitir animaciones, etc.)
Volviendo a su pregunta ...si el MemberRepository es responsable de ejecutar los get de los estados es irrelevante desde el punto de vista de ViewModel porque el repositorio es un servicio utilizado por el Modelo. El modelo es un servicio utilizado por ViewModel. Haga que su Modelo de la tarea/flujo de trabajo/proceso/lo que sea exponga la lista de opciones de estado.
Lo siento si fue largo aliento.