[英]Akka.NET and MVVM
我正在嘗試在我目前正在開發的新 WPF .NET Framework 應用程序中使用 Akka.NET。
大多數情況下,在您的應用程序中使用 actor 的過程似乎是不言自明的,但是當談到在應用程序視圖級別實際使用 actor 輸出時,我有點卡住了。
具體來說,關於如何在actor 中處理接收和處理事件,似乎有兩種選擇。
創建一個帶有公開事件處理程序的參與者。 所以也許是這樣的:
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 鼓勵的“Actors '無處不在'模型”,我不確定這種方法對並發的影響。
另一種選擇似乎是讓我的 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
實例時IActorRef
但不幸的是我無法將 actor 引用轉換回我需要的實際對象(在本例中為BaseViewModel
)。
所以如果我嘗試這樣做return (BaseViewModel)result;
我收到無效的強制轉換異常。 這顯然是有道理的,因為我得到的是IActorRef
對象而不是BaseViewModel
。
所以總而言之,我希望得到兩個問題的答案。
在 MVVM 應用程序中處理 Akka.NET actor 的最佳方法是什么,特別是在處理收到的消息和處理顯示輸出時。
有沒有辦法正確配置我的 Ioc 系統以創建一個IActorRef
實例並將其添加到系統中,但返回BaseViewModel
的實際父actor對象具體實現的實例?
以下是我正在使用的當前解決方案,希望有人能提出更好的建議。
基本上我已經放棄了讓我的視圖演員的嘗試,目前決定使用接口在ViewModel
和Actor
之間進行通信。
當前的解決方案如下所示:
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 輸出的更好解決方案的見解。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.