prisme vs wpf, mvvm light
nous sommes en train de lancer un FPF avec le projet MVVM et nous devons décider du prisme ou de la lumière MVVM (je suis nouveau dans ces deux cadres). J'ai lu quelques posts mais encore quelques questions. Est-ce que quelqu'un peut s'il vous plaît jeter un peu de lumière sur les aspects suivants W. R. T. les deux cadres?:
Performance: est-ce que l'un ou l'autre cadre donnera de meilleurs résultats que l'autre pour une raison quelconque?
Communication au sein de l'application (viewmodel à viewmodel ou entre modules etc): j'ai lu que MVVM Light a un service de messagerie qui semble être assez facile aussi bien. Mais PRISME ne semble pas avoir d'équivalent. Est-ce vrai? Comment PRISM gérerait-il les interactions?
test de L'Unité: on a lu que PRISM supporte mieux les tests de L'Unité. Peut-on encore écrire des tests NUNIT ou VSTS à la lumière MVVM?
3 réponses
je viens de déplacer un projet de Prism à MvvmLight et il semble fonctionner plus vite (très subjectif).
Prism et Mvmlight ont tous deux la réalisation de médiateur (Ieventagregator dans Prism, IMessenger dans Mvmlight). Mais IMessenger a plus de capacités (par exemple, envoyer des messages avec des jetons) par rapport à Ieventagregator et est beaucoup plus pratique à utiliser (voir l'article suivant).
MvvmLight dispose également d'une base de visualisation plus puissante classe.
les Applications qui utilisent Mvmlight sont beaucoup plus faciles à tester que celles qui utilisent Prism. Par exemple, IMessenger est plus facile à moquer que Ieventagregator.
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);
}
}
Inconvénients de Prisme:
c'est non entièrement projet open-source (officiel Prisme du référentiel en lecture seule)- 2015-10-30: maintenant, il est entièrement open-source: https://github.com/PrismLibrary/Prism
elle ne s'est plus développée activement- 2015-10-30: nouvelle version de Prism: https://github.com/PrismLibrary/Prism
- l'utilisation directe de ses classes conduit à la plaque chauffante et au code moins lisible
je pense que tout nouveau projet devrait être basé sur des solutions et des approches modernes. IMHO, tout MVVM-framework moderne (comme Catel, Caliburn.Micro, MvvmLight, ReactiveUI) est beaucoup mieux que Prism.
vous ne pouvez pas comparer complètement Prism et MvvmLight.
Prism est plus sur l'architecture d'application même si Prism a été connu comme MVVM framework. En fait jusqu'à Prism 5 il n'avait rien à voir avec MVVM et il n'avait pas la classe BaseViewModel dans Prism 4.1 et avant.
Prism n'est pas un cadre MVVM c'est un cadre d'application il se situe plus haut que cela. Prism 5 a introduit un certain soutien pour MVVM et Prism 6 l'a pris plus.
MVVM est juste un autre aspect des problèmes que prism fournit des conseils pour résoudre.
c'est comme comparer Angular vs. Knockout. AngularJS gère l'ensemble de l'application et définit des lignes directrices sur la façon dont le code d'application doit être structuré, alors qu'avec KnockoutJS la structure d'application est entièrement à vous. C'est un cas similaire entre Prism et MvvmLight.
Prism fournit une mise en œuvre d'un ensemble de modèles de conception qui sont utiles pour écrire bien structuré et les applications XAML maintenables, y compris MVVM, dependency injection, commanding, event aggregation, et plus encore. La fonctionnalité de base de Prism est une base de code partagée dans une bibliothèque de classe Portable ciblant ces plates-formes; WPF, Windows 10 UWP, et Xamarin formes.
je recommande D'utiliser Prism si vous développez une application au niveau de l'entreprise en utilisant wpf.
veuillez regarder ce webinaire sur MVVM Rendu Simple avec Prism. Le présentateur est Brian Lagunas: https://www.youtube.com/watch?v=ZfBy2nfykqY
Je ne crois pas que MS ait jamais promu PRISM comme un "cadre" dans le même sens que MVVM Light, Caliburn, etc. sont de la publicité."Ma compréhension est que le prisme a toujours été présenté au "monde" comme une " pratique."Ce qui, à mon avis, signifie simplement une façon organisée de créer des applications. Il devient un peu confus en raison de tout le code qui est fourni avec PRISM et on peut le considérer comme un "cadre" qui peut être utilisé pour construire des applications. Et, c'est vrai, vous pouvez utiliser le code qui est fourni avec PRISM pour construire vos propres applications. Mais, PRISM, dans mon esprit est beaucoup plus compliqué que les "cadres" qui sont disponibles pour MVVM et il ya une courbe d'apprentissage raide ainsi que la possibilité de "surmenage" et de rendre votre application plus complexe qu'il n'est nécessaire. Si vous avez le temps d'apprendre le dernier "cadre" ou "pratique" au moment où vous construisez votre application, C'est génial! Mon expérience a été que je n'ai pas le luxe de factoring dans l'apprentissage une nouvelle " pratique "ou le dernier" cadre", mais il faut que le travail soit fait. Dans un monde idéal, on aimerait pouvoir utiliser le dernier et le plus grand "cadre" ou employer les dernières "pratiques", mais parfois, il suffit de s'en tenir à ce que vous savez déjà et de le faire.