studio - prisma vs luz mvvm para wpf
visual studio wpf (3)
Acabo de mover un proyecto de Prism a MvvmLight y parece funcionar más rápido (muy subjetivo).
Tanto Prism como MvvmLight tienen la realización de Mediator (IEventAggregator en Prism, IMessenger en MvvmLight). Pero IMessenger tiene más habilidades (por ejemplo, el envío de mensajes con tokens) en comparación con IEventAggregator y es mucho más cómodo de usar (ver siguiente artículo).
MvvmLight también tiene una clase ViewModelBase más poderosa.
Las aplicaciones que usan MvvmLight son mucho más fáciles de probar que las que usan Prism. Por ejemplo, IMessenger es más fácil de burlar que IEventAggregator.
PrismViewModel.cs
using System;
using Microsoft.Practices.Prism.Events;
using Microsoft.Practices.Prism.ViewModel;
// An ugly empty event class
public class StringEvent : CompositePresentationEvent<string> { }
public sealed class PrismViewModel : NotificationObject
{
private readonly IEventAggregator _eventAggregator;
private string _name;
public PrismViewModel(IEventAggregator eventAggregator)
{
if (eventAggregator == null)
throw new ArgumentNullException("eventAggregator");
_eventAggregator = eventAggregator;
_eventAggregator.GetEvent<StringEvent>().Subscribe(s => Name = s);
}
public string Name
{
get { return _name; }
set
{
// boiler-plate code
if (value == _name)
return;
_name = value;
RaisePropertyChanged(() => Name);
}
}
public void SendMessage(string message)
{
_eventAggregator.GetEvent<StringEvent>().Publish(message);
}
}
PrismViewModelTestCase.cs
using System;
using FluentAssertions;
using Microsoft.Practices.Prism.Events;
using NSubstitute;
using NUnit.Framework;
public class PrismViewModelTestCase
{
private static PrismViewModel CreateViewModel(IEventAggregator eventAggregator = null)
{
// You can''t return Substitute.For<IEventAggregator>()
// because it returns null when PrismViewModel''s constructor
// invokes GetEvent<StringEvent>() method which leads to NullReferenceException
return new PrismViewModel(eventAggregator ?? CreateEventAggregatorStub());
}
private static IEventAggregator CreateEventAggregatorStub()
{
var eventAggregatorStub = Substitute.For<IEventAggregator>();
eventAggregatorStub.GetEvent<StringEvent>().Returns(Substitute.For<StringEvent>());
return eventAggregatorStub;
}
[Test]
public void Constructor_WithNonNullEventAggregator_ExpectedSubscribesToStringEvent()
{
// Arrange
var stringEventMock = Substitute.For<StringEvent>();
var eventAggregatorStub = Substitute.For<IEventAggregator>();
eventAggregatorStub.GetEvent<StringEvent>().Returns(stringEventMock);
// Act
CreateViewModel(eventAggregatorStub);
// Assert
// With constrained isolation framework you can only mock virtual members
// CompositePresentationEvent<TPayload> has only one virtual Subscribe overload with four parameters
stringEventMock.Received()
.Subscribe(Arg.Any<Action<string>>(), Arg.Any<ThreadOption>(), Arg.Any<bool>(),
Arg.Any<Predicate<string>>());
}
[Test]
public void Name_ExpectedRaisesPropertyChanged()
{
var sut = CreateViewModel();
sut.MonitorEvents();
sut.Name = "any-value";
sut.ShouldRaisePropertyChangeFor(vm => vm.Name);
}
[Test]
public void SendMessage_ExpectedPublishesStringEventThroughEventAggregator()
{
// Arrange
var stringEventMock = Substitute.For<StringEvent>();
var eventAggregatorStub = Substitute.For<IEventAggregator>();
eventAggregatorStub.GetEvent<StringEvent>().Returns(stringEventMock);
var sut = CreateViewModel(eventAggregatorStub);
const string expectedPayload = "any-string-payload";
// Act
sut.SendMessage(expectedPayload);
// Assert
stringEventMock.Received().Publish(expectedPayload);
}
}
MvvmLightViewModel.cs
using System;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Messaging;
public sealed class MvvmLightViewModel : ViewModelBase
{
private string _name;
public MvvmLightViewModel(IMessenger messenger)
{
if (messenger == null)
throw new ArgumentNullException("messenger");
// ViewModelBase already have field for IMessenger
MessengerInstance = messenger;
MessengerInstance.Register<string>(this, s => Name = s);
}
public string Name
{
get { return _name; }
set { Set(() => Name, ref _name, value); // Chic! }
}
public void SendMessage(string message)
{
MessengerInstance.Send(message);
}
}
MvvmLightViewModelTestCase.cs
using System;
using FluentAssertions;
using GalaSoft.MvvmLight.Messaging;
using NSubstitute;
using NUnit.Framework;
public class MvvmLightViewModelTestCase
{
private static MvvmLightViewModel CreateViewModel(IMessenger messenger = null)
{
return new MvvmLightViewModel(messenger ?? Substitute.For<IMessenger>());
}
[Test]
public void Constructor_WithNonNullMessenger_ExpectedRegistersToStringMessage()
{
var messengerStub = Substitute.For<IMessenger>();
var sut = CreateViewModel(messengerStub);
messengerStub.Received().Register(sut, Arg.Any<Action<string>>());
}
[Test]
public void Name_ExpectedRaisesPropertyChanged()
{
var sut = CreateViewModel();
sut.MonitorEvents();
sut.Name = "any-value";
sut.ShouldRaisePropertyChangeFor(vm => vm.Name);
}
[Test]
public void SendMessage_ExpectedSendsStringMessageThroughMessenger()
{
var messengerMock = Substitute.For<IMessenger>();
var sut = CreateViewModel(messengerMock);
const string expectedMessage = "message";
sut.SendMessage(expectedMessage);
messengerMock.Received().Send(expectedMessage);
}
}
Desventajas del prisma:
no es un proyecto de código abierto (el repositorio oficial de Prism es de solo lectura)- 2015-10-30 : ahora es de código abierto: https://github.com/PrismLibrary/Prism
ya no se desarrolló activamente- 2015-10-30 : nueva versión de Prism: https://github.com/PrismLibrary/Prism
- el uso directo de sus clases conduce a la placa de la caldera y al código menos legible
Creo que cualquier proyecto nuevo debe basarse en soluciones y enfoques modernos. En mi humilde opinión, cualquier MVVM-framework moderno (como Catel, Caliburn.Micro, MvvmLight, ReactiveUI) es mucho mejor que Prism.
Estamos comenzando un proyecto WPF con MVVM y tenemos que decidir sobre PRISM o MVVM Light (soy nuevo en estos dos marcos). He leído algunas publicaciones pero todavía tengo algunas preguntas. ¿Alguien puede por favor arrojar algo de luz sobre los siguientes aspectos tanto de los marcos ?:
Rendimiento: ¿Funcionará alguna de las dos estructuras mejor que la otra por algún motivo?
Comunicación dentro de la aplicación (modelo de vista para ver el modelo o entre módulos, etc.): He leído que MVVM Light tiene un servicio de Messenging que también parece ser bastante fácil. Pero PRISM no parece tener ningún equivalente. ¿Es eso cierto? ¿Cómo manejaría PRISM las interacciones?
Pruebas unitarias: He leído que PRISM soporta mejor las Pruebas unitarias. ¿Todavía podemos escribir pruebas NUNIT o VSTS en MVVM Light también?
No creo que MS haya promovido PRISM como un "marco" en el mismo sentido en que MVVM Light, Caliburn, etc. son "publicitados". Mi comprensión es que el PRISMA siempre fue presentado al "mundo" como una "práctica". Lo cual, creo, simplemente significa una forma organizada de crear aplicaciones. Se vuelve un poco confuso debido a todo el código que se proporciona con PRISM y uno puede considerarlo como un "marco" que puede usarse para crear aplicaciones. Y, es cierto, puede usar el código que se proporciona con PRISM para crear sus propias aplicaciones. Pero, PRISM, en mi opinión es mucho más complicado que los "marcos" que están disponibles para MVVM y hay una curva de aprendizaje abrupta, así como la posibilidad de "exceso" y hacer que su aplicación sea más compleja de lo necesario. Si tiene tiempo para aprender el último "marco" o "práctica" en el momento en que está construyendo su aplicación, ¡eso es GENIAL! Mi experiencia ha sido que no tengo el lujo de tener en cuenta el aprendizaje de una nueva "práctica" o el último "marco", sino que tengo que hacer el trabajo. En un mundo ideal, a uno le gustaría poder usar el último y mejor "marco" o emplear las últimas "prácticas", pero a veces solo tiene que quedarse con lo que ya sabe y hacerlo funcionar.
No puede comparar completamente Prism y MvvmLight.
Prism se trata más de arquitectura de aplicaciones, aunque Prism se conoce como framework MVVM. En realidad, hasta Prism 5 no tenía nada que ver con MVVM y no tenía la clase BaseViewModel en Prism 4.1 y en versiones anteriores.
Prism no es un framework de MVVM, es un marco de aplicación que se encuentra más arriba que eso. Prism 5 introdujo algo de soporte para MVVM y Prism 6 lo llevó más allá.
MVVM es solo otro aspecto de los problemas que el prisma proporciona una guía para resolver.
Es como comparar Angular vs. Knockout. AngularJS maneja toda la aplicación y define pautas sobre cómo se debe estructurar el código de la aplicación, mientras que con KnockoutJS la estructura de la aplicación depende completamente de usted. Es un caso similar entre Prism y MvvmLight.
Prism proporciona una implementación de una colección de patrones de diseño que son útiles para escribir aplicaciones XAML bien estructuradas y mantenibles, incluyendo MVVM, inyección de dependencia, comando, agregación de eventos y más. La funcionalidad principal de Prism es una base de código compartido en una Biblioteca de clases portátil dirigida a estas plataformas; WPF, Windows 10 UWP y Xamarin Forms.
Recomendaría utilizar Prism si está desarrollando una aplicación de nivel empresarial con wpf.
Mire este seminario web sobre MVVM Made Simple with Prism. El presentador es Brian Lagunas: https://www.youtube.com/watch?v=ZfBy2nfykqY