Akka.NET和MVVM

问题描述 投票:2回答:1

我正在使用我正在开发的新WPF .NET Framework应用程序中使用Akka.NET。

大多数情况下,在应用程序中使用actor的过程似乎是不言而喻的,但是,在应用程序视图级别实际使用actor输出时,我有点卡住了。

特别是关于如何处理actor中的接收和处理事件,似乎有两个选择。

  1. 创建具有公开事件处理程序的演员。所以也许是这样的:

    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);
        }
    }
    

因此,基本上,您可以通过执行类似_doActionActor.Tell(new GetStuffRequest());的操作来创建视图并调用任何调用,然后通过事件处理程序处理输出。这很好用,但似乎破坏了Akka.NET鼓励的“参与者“无处不在”模型”,而且我不确定这种方法对并发的影响。

  1. 替代方案似乎是实际上使我的ViewModels是演员本身。所以基本上我有这样的东西。

    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)
        {
    
        }
    }
    

这样,我可以直接在actor本身(实际上是我的视图模型)中处理actor事件。

我尝试执行此操作时遇到的问题是正确配置Ioc(Castle Windsor)以正确构建Akka.NET实例。

所以我有一些代码来创建如下所示的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;
                }))

不幸的是,这在实际创建IActorRef实例时非常有用,但是我无法将actor引用强制转换回所需的实际对象(在这种情况下为BaseViewModel)。

因此,如果我尝试执行此操作return (BaseViewModel)result;,则会收到无效的强制转换异常。这显然是有道理的,因为我得到的是IActorRef对象而不是BaseViewModel

因此,总而言之,我希望回答两个问题。

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

  2. 有没有一种方法可以正确配置我的Ioc系统,以创建一个IActorRef实例并将其添加到系统中,但返回BaseViewModel的实际父actor对象的具体实例的实例,] [

c# akka castle-windsor akka.net akka-remote-actor
1个回答
1
投票

下面是我正在使用的当前解决方案,希望有人可以提出更好的建议。

[基本上,我已经放弃了使我的视图参与者成为现实的尝试,目前决定使用接口在ViewModelActor之间进行通信。

当前解决方案如下:

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);
    }

}

虽然我不觉得这是理想的,但它基本上让我避免了试图使我自己的视图模型自身成为演员,同时又将演员与视图充分分离的所有额外的复杂性。

我希望其他人已经遇到了这个问题,也许能够在更好的解决方案中提供一些见识,以便在MVVM应用程序中处理Akka.NET输出。

© www.soinside.com 2019 - 2024. All rights reserved.