简体   繁体   English

Akka.NET 和 MVVM

[英]Akka.NET and MVVM

I am playing around with using Akka.NET in a new WPF .NET Framework application I am currently working on.我正在尝试在我目前正在开发的新 WPF .NET Framework 应用程序中使用 Akka.NET。

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.大多数情况下,在您的应用程序中使用 actor 的过程似乎是不言自明的,但是当谈到在应用程序视图级别实际使用 actor 输出时,我有点卡住了。

Specifically there appear to be two options on how you might handle receiving and processing events in your actor.具体来说,关于如何在actor 中处理接收和处理事件,似乎有两种选择。

  1. 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());所以基本上你可以创建你的视图并通过做这样的事情来调用任何调用_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.这很有效,但似乎打破了 Akka.NET 鼓励的“Actors '无处不在'模型”,我不确定这种方法对并发的影响。

  1. The alternative appears to be to actually make it such that my ViewModels are actors themselves.另一种选择似乎是让我的 ViewModels 本身就是演员。 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).这样我就可以直接在 actor 本身(实际上是我的视图模型)中处理 actor 事件。

The problem I run into when trying to do this is correctly configuring my Ioc (Castle Windsor) to correctly build Akka.NET instances.我在尝试执行此操作时遇到的问题是正确配置我的 Ioc(Castle Windsor)以正确构建 Akka.NET 实例。

So I have some code to create the Akka.NET object that looks like this所以我有一些代码来创建看起来像这样的 Akka.NET 对象

        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 ).这在实际创建IActorRef实例时IActorRef但不幸的是我无法将 actor 引用转换回我需要的实际对象(在本例中为BaseViewModel )。

So if I try to do this return (BaseViewModel)result;所以如果我尝试这样做return (BaseViewModel)result; I get an invalid cast exception.我收到无效的强制转换异常。 Which obviously makes sense because I am getting an IActorRef object not a BaseViewModel .这显然是有道理的,因为我得到的是IActorRef对象而不是BaseViewModel

So in conclusion I am hoping to get two questions answered.所以总而言之,我希望得到两个问题的答案。

  1. 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.在 MVVM 应用程序中处理 Akka.NET actor 的最佳方法是什么,特别是在处理收到的消息和处理显示输出时。

  2. 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 ?有没有办法正确配置我的 Ioc 系统以创建一个IActorRef实例并将其添加到系统中,但返回BaseViewModel的实际父actor对象具体实现的实例?

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 .基本上我已经放弃了让我的视图演员的尝试,目前决定使用接口在ViewModelActor之间进行通信。

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.我希望其他人也遇到过这个问题,并且可能能够提供一些关于在 MVVM 应用程序中处理 Akka.NET 输出的更好解决方案的见解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM