We are starting a WPF with MVVM project and have to decide on PRISM or MVVM Light (I am new to both these frameworks). I have read through a few posts but still have a few questions. Can someone please throw some light on the following aspects w.r.t. both the frameworks?:
Performance: Will either one framework perform better than the other for any reason?
Communication within the app (viewmodel to viewmodel or between modules etc): I have read that MVVM Light has Messenging Service which appears to be fairly easy as well. But PRISM does not appear to have any equivalent. Is that true? How would PRISM handle interactions?
Unit Testing: Have read that PRISM supports Unit Testing better. Can we still write NUNIT or VSTS tests in MVVM Light also?
Prism is a framework for building loosely coupled, maintainable, and testable XAML applications in WPF, and Xamarin Forms. Separate releases are available for each platform and those will be developed on independent timelines.
The difference is that MVVM Light wraps a lot of this in a view-model locator—a static class used to register services and get view models. MvvmCross has some setup code provided by the framework, and inside this setup code you initialize the content of the IoC container.
MVVM-light is a toolkit written in C# which helps to accelerate the creation and development of MVVM applications in WPF, Silverlight, Windows Store, Windows Phone and Xamarin.
Answers: 1) Prism is an MVVM framework to use as a foundation for your applications. 2) I suggest so depending on your specific requirements. You should post another question with specific details so you can get some specific answers. 3) Prism uses dependency injection (Unity) but does not "provide" it.
I just moved a project from Prism to MvvmLight and it seems to work faster (very subjective).
Both Prism and MvvmLight have Mediator realisation (IEventAggregator in Prism, IMessenger in MvvmLight). But IMessenger has more abilities (for instance, sending messages with tokens) compared to IEventAggregator and is much more convenient to use (see next item).
MvvmLight also has a more powerful ViewModelBase class.
Applications that use MvvmLight are much easier to test than those that use Prism. For instance, IMessenger is easier to mock than 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); } }
Disadvantages of Prism:
I think that any new project should be based on modern solutions and approaches. IMHO, any modern MVVM-framework (like Catel, Caliburn.Micro, MvvmLight, ReactiveUI) is much better than Prism.
You cannot fully compare Prism and MvvmLight.
Prism is more about application architecture even though Prism has been known as MVVM framework. Actually until Prism 5 it had nothing to do with MVVM and It didn't have BaseViewModel class in Prism 4.1 and in prior.
Prism is not a MVVM framework it is application framework it sits higher than that. Prism 5 introduced some support for MVVM and Prism 6 took it futher.
MVVM is just another aspect of problems that prism provides guidance to solve.
It is like comparing Angular vs. Knockout. AngularJS manages the whole application and defines guidelines on how the application code should be structured, whereas with KnockoutJS the application structure is entirely up to you. It is a similar case between Prism and MvvmLight.
Prism provides an implementation of a collection of design patterns that are helpful in writing well structured and maintainable XAML applications, including MVVM, dependency injection, commanding, event aggregation, and more. Prism's core functionality is a shared code base in a Portable Class Library targeting these platforms; WPF, Windows 10 UWP, and Xamarin Forms.
I would recommend to use Prism if you are developing an enterprise level application using wpf.
Please watch this Webinar about MVVM Made Simple with Prism. The presenter is Brian Lagunas: https://www.youtube.com/watch?v=ZfBy2nfykqY
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With