Akka.NET and MVVM - c#

I am playing around with using Akka.NET in a new WPF .NET Framework application I am currently working on.
Mostly the process of using actors in your application seems pretty self explanitory, however when it comes to actually utilising the actor output at the application view level I have gotten a bit stuck.
Specifically there appear to be two options on how you might handle receiving and processing events in your actor.
Create an actor with publically exposed event handlers. So maybe something like this:
public class DoActionActor : ReceiveActor
{
public event EventHandler<EventArgs> MessageReceived;
private readonly ActorSelection _doActionRemoteActor;
public DoActionActor(ActorSelection doActionRemoteActor)
{
this._doActionRemoteActor = doActionRemoteActor ?? throw new ArgumentNullException("doActionRemoteActor must be provided.");
this.Receive<GetAllStuffRequest>(this.HandleGetAllStuffRequestReceived);
this.Receive<GetAllStuffResponse>(this.HandleGetAllStuffResponseReceived);
}
public static Props Props(ActorSystem actorSystem, string doActionRemoteActorPath)
{
ActorSelection doActionRemoteActor = actorSystem.ActorSelection(doActionRemoteActorPath);
return Akka.Actor.Props.Create(() => new DoActionActor(doActionRemoteActor));
}
private void HandleGetAllStuffResponseReceived(GetAllTablesResponse obj)
{
this.MessageReceived?.Invoke(this, new EventArgs());
}
private void HandleGetAllStuffRequestReceived(GetAllTablesRequest obj)
{
this._doActionRemoteActor.Tell(obj, this.Sender);
}
}
So basically you can then create your view and invoke any calls by doing something like this _doActionActor.Tell(new GetStuffRequest()); and then handle the output through the event handler. This works well but seems to break the 'Actors 'everywhere' model' that Akka.NET encourages and I am not sure about the concurrency implications from such an approach.
The alternative appears to be to actually make it such that my ViewModels are actors themselves. So basically I have something that looks like this.
public abstract class BaseViewModel : ReceiveActor, IViewModel
{
public event PropertyChangedEventHandler PropertyChanged;
public abstract Props GetProps();
protected void RaisePropertyChanged(PropertyChangedEventArgs eventArgs)
{
this.PropertyChanged?.Invoke(this, eventArgs);
}
}
public class MainWindowViewModel : BaseViewModel
{
public MainWindowViewModel()
{
this.Receive<GetAllTablesResponse>(this.HandleGetAllTablesResponseReceived);
ActorManager.Instance.Table.Tell(new GetAllTablesRequest(1), this.Self);
}
public override Props GetProps()
{
return Akka.Actor.Props.Create(() => new MainWindowViewModel());
}
private void HandleGetAllTablesResponseReceived(GetAllTablesResponse obj)
{
}
}
This way I can handle actor events directly in actors themselves (which are actually my view models).
The problem I run into when trying to do this is correctly configuring my Ioc (Castle Windsor) to correctly build Akka.NET instances.
So I have some code to create the Akka.NET object that looks like this
Classes.FromThisAssembly()
.BasedOn<BaseViewModel>()
.Configure(config => config.UsingFactoryMethod((kernel, componentModel, context) =>
{
var props = Props.Create(context.RequestedType);
var result = ActorManager.Instance.System.ActorOf(props, context.RequestedType.Name);
return result;
}))
This works great at actually creating an instance of IActorRef BUT unfortunately I cannot cast the actor reference back to the actual object I need (in this case BaseViewModel).
So if I try to do this return (BaseViewModel)result; I get an invalid cast exception. Which obviously makes sense because I am getting an IActorRef object not a BaseViewModel.
So in conclusion I am hoping to get two questions answered.
What is the best way to deal with Akka.NET actors in MVVM applications, specifically when it comes to handling messages received and handling displaying the output.
Is there a way to correctly configure my Ioc system to both create an IActorRef instance and add it to the system BUT return an instance of the actual parent actor object concrete implementation of BaseViewModel?

Below is the current solution that I am using in the hope someone might propose something a bit better.
Basically I have abandoned my attempt at making my views actors and currently settled on using an interface to communicate between the ViewModel and Actor.
The current solution looks like this:
public class MainWindowViewModel : BaseViewModel, ITableResponseHandler
{
public void HandleResponse(IEnumerable<Entity> allEntities) { }
}
public interface ITableResponseHandler
{
void HandleResponse(IEnumerable<Entity> allEntities);
}
public class MyActor : ReceiveActor
{
public MyActor(ITableResponseHandler viewModel)
{
this.Receive<GetAllEntitiesResponse>(this.HandleGetAllEntitiesResponseReceived);
}
private void HandleGetAllEntitiesResponseReceived(GetAllTablesResponse obj)
{
this._ViewModel.HandleTablesResponse(obj.Result);
}
}
While I don't feel this is ideal it basically lets me avoid all the extra complexity of trying to make my view models themselves actors while sufficently decoupling the actor from the view.
I hope someone else has faced this problem and might be able to provide some insight at a better solution for handling Akka.NET output in a MVVM application.

Related

Generic Payload for Prism Event Aggregator

I am developing an WPF application and tried to design something event driven using Prism's Event Aggregator.
Currently I am trying to implement something like event queue for Prism events.
To do that I want to subscribe related events and pass them to same method but Event Aggregator wants those methods to have same signature with the event.
Example events:
public class TestEvent1 : PubSubEvent<Class1>
{
}
public class TestEvent2 : PubSubEvent<Class2>
{
}
public class TestEvent3 : PubSubEvent<List<Class3>>
{
}
public class TestEvent3 : PubSubEvent<string>
{
}
Subscriptions:
_eventAggregator.GetEvent<TestEvent1>().Subscribe(OnTestEvent1, true);
_eventAggregator.GetEvent<TestEvent2>().Subscribe(OnTestEvent2, true);
_eventAggregator.GetEvent<TestEvent3>().Subscribe(OnTestEvent3, true);
Example callback method:
private void OnTestEvent1(Class1 object1)
{
// do something
}
Since I only receive data when event published, I tried something like this to use as event payload type, but it doesn't look right:
// Payload
public interface IMessage
{
public object Data { get; set; }
public Type Datatype { get; set; }
public PubSubEvent EventType { get; set; }
}
// Events
public class TestEvent1 : PubSubEvent<IMessage>
{
}
public class TestEvent2 : PubSubEvent<IMessage>
{
}
public class TestEvent3 : PubSubEvent<IMessage>
{
}
// Subscriptions
_eventAggregator.GetEvent<TestEvent1>().Subscribe(EventHandler, true);
_eventAggregator.GetEvent<TestEvent2>().Subscribe(EventHandler, true);
_eventAggregator.GetEvent<TestEvent3>().Subscribe(EventHandler, true);
// Callback
private void EventHandler(IMessage payload)
{
// do something
}
Is this viable and how can I improve or change my "generic" payload?
Extra information:
In my scenario I have multiple UDP servers that periodically receives new data, deserialize it to objects and publish events.
Related "managers" subscribed to those events and get triggered when new data received.
My goal is try to implement an event queue like system in my event receiving classes so it will be easier to deal with multithreading issues.
Here are some diagrams that may help me explain myself better:
My architecture:
My "event queue"
This is more of a code-review question, isn't it?
I would very much prefer strong typing, though, and I wouldn't want to build a queue around the event aggregator, that will always be tedious because you never know when new event types show up. Instead, I'd build my own event aggregator with queueing built in (starting from the existing one).
Also, I'd look into dataflow, for example, because the basic working mode of the event aggregator (fire and forget, one sender, multiple or no receivers) doesn't seem to work well with queueing. If you queue at the sender-side, to you wait for one receiver or all? Do you queue when there are no receivers or do you discard then? If you queue at the receiver-side, why bother at all? The receiver can implement the queue on its own.
When you publish an event with a reference to an object, consider these potential problems:
Any listener will be dependent on the type/assembly of the event parameter.
The referenced object will be held for some time. For how long? You don't know.
The referenced object could have been altered/disposed.
Listeners might handle the referenced object on a different thread.
After dealing with PubSubEvent<T> for several years now, I believe there is only one suitable pattern that successfully handles all cases. Publish your event with a unique identifier, e.g. a Guid.
public class MyItemAddedEvent : PubSubEvent<Guid> {}
Then inject a provider wherever you listen for this event:
public class SomeListener
{
private readonly IMyItemProvider myItemProvider;
[ImportingConstructor]
public SomeListener(IEventAggregator eventAggregator,
IMyItemProvider myItemProvider)
{
this.myItemProvider = myItemProvider;
eventAggregator.GetEvent<MyItemAddedEvent>().Subscribe(OnMyItemAdded, true);
}
private void OnMyItemAdded(Guid id)
{
var myItem = myItemProvider.Get(id);
// Do stuff
}
}
Now it is the responsibility of the provider class to deliver a valid and up-to-date object given a unique id.

How to notify all guard methods when global changes

Often in my applications built with Caliburn Micro I have a need to store some global data; this could be app specific config, authentication properties, etc. I generally put them in a class called "Session" and inject that via constructor injection so that every view model has a reference to a single instance of Session.
I found a case where I wanted a guard method on two different view models to be linked to a Session variable; the issue is guard methods are generally notified of changes in the setter of the changed variable. Since it's a global, it doesn't know what depends on it. (It occurs to me that this pattern of variables being aware of what guard is hooked into them is bad, but when it's all in the same ViewModel it doesn't matter much.)
I could throw an event, but that's messy and a lot of work for something that should be simple.
I could try to identify every spot where it may have been updated and manually notify, but that's error prone.
public class MyViewModel: Screen{
public MyViewModel(SessionInfo session){
Session = session;
}
public CanTakeAction { get { return !string.isNullOrWhitespace(Session.SomeProperty); } }
}
public class SessionInfo {
public SessionInfo(){}
public string SomeProperty { get; set; }
// this is where I would normally notify a guard method, but this is not going to work
NotifyOfPropertyChange(() => CanTakeAction); // except it doesn't know about CanTakeAction
}
One possible solution would be to introduce a base ViewModel, which has the guard methods (virtual). For Example,
public class ViewModelBase:Screen
{
private SessionInfo _sessionInfo;
public ViewModelBase(SessionInfo sessionInfo)
{
_sessionInfo = sessionInfo;
}
public void NotifyGuardMethods()
{
NotifyOfPropertyChange(nameof(CanTakeAction));
}
public virtual bool CanTakeAction { get; set; } = false;
}
For all the ViewModels that needs to be notified by the change in Session, you could now derieve from the ViewModelBase.
public class ShellViewModel:ViewModelBase
{
public override bool CanTakeAction { get=>//its own logic; set=>//its own logic; };
}
You could now introduce Events to the ViewModelBase, which could use the NotifyGuardMethods defined in the base class to notify all other view models. This ensures the messsy Events part would be restricted to one class alone (base view model).

How to execute action whenever MEF instantiates (exports) new object?

I'm building a modular app with MEF, and been trying to come up with smart ideas how handle saving/loading states.
In certain situations (eg when user clicks "save"), my shell will have to trigger some sort of save/load action, which plugins may want to be aware of to be able to save and load their own states.
There are a lot of possible ways of course including events and a global message bus, however my preferred idea at the moment is based on two interfaces:
public interface ISaveAndLoadState
{
void SaveState(XmlWriter writer);
void LoadState(XmlReader reader);
}
public interface IStateManager
{
void Register(ISaveAndLoadState item);
void Save(Stream stream);
void Load(Stream stream);
}
Then plugins - their modules, view models or anything - could do the following:
[Export]
public class iAmAPluginViewModelOrModule : ISaveAndLoadState
{
[ImportingConstructor]
public iAmAPluginViewModelOrModule(IStateManager m)
{
m.Register(this);
}
public void SaveState(XmlWriter writer) { ..... }
public void LoadState(XmlReader reader) { ..... }
}
This should work reasonably well. However, I think it'd be even nicer if classes that implement ISaveAndLoadState wouldn't have to call IStateManager.Register() explicitly - but rather that when MEFs instantiates a class implementing ISaveAndLoadState, it automatically registers it with the IStateManager.
So basically, I'd need an "event" triggering whenever MEF instantiates any new object, and then do something like
public void OnMefHasCreatedInstance(object instance)
{
var _inst = instance as ISaveAndLoadState;
if(_inst != null)
Container.GetExportedValue<IStateManager>().Register(_inst);
}
Is that possible at all? Is there any way to listen to / be informed to when MEF has created a new instsance?
This isn't quite answering your question but it is possibly another solution for you.
If you export each class with the ISaveAndLoadState interface, then you can use an ImportMany within your StateManager
[Export(typeof(ISaveAndLoadState))]
public class iAmAPluginViewModelOrModule : ISaveAndLoadState
public class StateManager : IStateManager
{
[ImportMany(typeof(ISaveAndLoadState))]
private List<ISaveAndLoadState> _saveAndLoadStates;
}
Then _saveAndLoadStates should be populated with all of your objects and you can just loop through them in the StateManager Load and Save methods.

Decoupling ViewModels in MVVM

I know that in MVVM pattern (or possibly in any design pattern of this kind) we should keep our layers decoupled. From my understanding it also means, that I should keep my ViewModels separate. I'm having a bit trouble following this rule.
Say - I have a ConversationViewModel and a MessageViewModel - the former needs to create instances of the later. When ConversationViewModel gets notification about incoming message it spawns a new MessageViewModel instance and fills it with data.
The question is - if I create new MessageViewModel instances explicitly in the ConversationViewModel won't it make my app a bit harder to test? I mean - one unit of code is the ConversationViewModel and other is the MessageViewModel - I'd like to test both separate, so when somebody breaks something in the later, test for the former won't be affected. How do I achieve it?
I'm using MVVMLight, so I thought I would register MessageViewModel as an implementation of some interface, and then create a class like MockMessageViewModel implementing the same interface, but used only in tests. Then in the ConversationViewModel I'd ask the IOC container to just give me the registered implementation. Is it a good approach, or am I overreacting? Example code:
public class ViewModelLocator {
public ViewModelLocator() {
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (//in test) {
SimpleIoc.Default.Register<IMessageViewModel, MockMessageViewModel>();
}
else {
SimpleIoc.Default.Register<IMessageViewModel, MessageViewModel>();
}
}
public class ConversationViewModel : ViewModelBase {
public void MessageReceived(string data) {
//I'm thinking about doing this:
var vm = SimpleIoc.Default.GetInstance<IMessageViewModel>();
// instead of doing this
var vm = new MessageViewModel();
//do stuff with vm
}
}
Whether to use interface bases approach to separate the view models from each other is the design decision based on complexity of your application.
If you want to dynamically create instance of IMessageViewModel inside IConvesationViewModel; I would recommend instead of referring to IoC container in your ViewModel class inject a factory for creating IMessageViewModel in the ConversationViewModel constructor. Later you can use this factory to create instances of IMessageViewModel. A simple implementation of factory could be Func delegate.
public class ConversationViewModel
{
private Func<IMessageViewModel> _messageViewModelFactory;
public ConversationViewModel(Func<IMessageViewModel> messageViewModelFactory)
{
_messageViewModelFactory = messageViewModelFactory;
}
public void MessageReceived(string data) {
var messageViewModel = _messageViewModelFactory();
}
}
This way you are exposing dependencies of your ConversationViewModel class through the constrctor instead of hiding them inside the class implementation.
The IoC containers like Autofac provide way to inject Func in the constructor when you create object of ConversationViewModel using it.
I believe a better way to do that is by using interfaces. You can have both your real and mock ViewModels implement the same interface and use that interface everywhere where you would use a ViewModel class.
If it was me and I may not have all the information about your application but I would have a single ViewModel IConversationViewModel. And in the IConversationViewModel I would have a collection of IMessageModel instances. I would not go nesting ViewModels.
What you can do is create the MessageViewModel immediately in ViewModelLocator and register for receiving messages in MessageViewModel using the MVVMLight MessengerInstance in its constructor. Something like this:
public class ViewModelLocator
{
public class ViewModelLocator()
{
//creates instance immediately
SimpleIoc.Default.Register<MessageViewModel>(true);
}
}
public class MessageViewModel:ViewModelBase
{
public MessageViewModel()
{
MessengerInstance.Register<string>(this,DoSomething);
}
public void DoSomething(string data)
{
//do stuff
}
}
public class ConversationViewModel:ViewModelBase
{
public void MessageReceived(string data)
{
MessengerInstance.Send<string>(data);//this will trigger DoSomething in MessageViewModel
}
}

Callback interface contract

I have two .NET parties who needs be bound by a contract. Now, party1 and party2 need to be able call some methods on each other (most of it is calls and reporting result back). I have duplex contract in mind, but the parties are not using WCF.
Is there a design pattern for this?
Edit
The parties are part of the same application. I create the application (party1) and someone else creates a dll (party2) that I load dynamically. Now, both of us should be able to call methods on each other. So, I am out to create an interface contract between us. The intent is to know whether there is a know pattern to do that?
A common solution is to use some kind of pub/sub pattern. By doing so you can avoid circular dependencies.
Basically you create some kind of class which are used to subscribe on events (and publish them).
So both your classes does something like this (but with different events):
public class ClassA : IEventHandler<UserCreated>
{
IEventManager _eventManager
public ClassA(IEventManager manager)
{
// I subscribe on this event (which is published by the other class)
manager.Subscribe<UserCreated>(this);
_eventManager = manager;
}
public void Handle(UserCreated theEvent)
{
//gets invoked when the event is published by the other class
}
private void SomeInternalMethod()
{
//some business logic
//and I publish this event
_eventManager.Publish(new EmailSent(someFields));
}
}
The event manager (simplified and not thread safe):
public class EventManager
{
List<Subscriber> _subscribers = new List<Subscriber>();
public void Subscribe<T>(IEventHandler<T> subscriber)
{
_subscribers.Add(new Subscriber{ EventType = typeof(T), Subscriber = subscriber});
}
public void Publish<T>(T theEvent)
{
foreach (var wrapper in subscribers.Where(x => x == typeof(theEvent)))
{
((IEventHandler<T>)wrapper.Subscriber).Handle(theEvent);
}
}
}
The small wrapper:
public class Subscriber
{
public Type EventType;
public object Subscriber;
}
Voila. the two classes are now loosely coupled from each other (while still being able to communicate with each other)
If you use an inversion of control container it get's easier since you can simplify the event manager and just use the container (service location) to resolve all subscribers:
public class EventManager
{
IYourContainer _container;
public EventManager(IYourContainer container)
{
_container = container;
}
public void Publish<T>(T theEvent)
{
foreach (var subscriber in _container.ResolveAll<IEventHandler<T>>())
{
subscriber.Handle(theEvent);
}
}
}
I think you can use next logic:
Class1: Interface1 , Class2:Interface2,
class Manager{
public Manager(Interface1 managedPart1,Interface2 managedPart2){
... some logic for connect to interfaces
}
}
This way reminds me pattern Bridge, but this is very subjective

Categories