簡體   English   中英

在異步上下文中使用 Bind

[英]Using Bind in an asynchronous context

我正在使用 `language-ext' package 作為 C# 試圖使我們的代碼更健壯,但在如何鏈接異步操作上苦苦掙扎。

考慮以下描述車輛的簡單 class 的抽象示例

public class MyVehicle
{
    public MyVehicle(string name)
    {
        Name = name;
    }

    public string Name { get; }

    public MyVehicle DeepCopy()
    {
        return new MyVehicle(Name);
    }
}

和另一個 class 存儲一些關於車輛的 state

public class MyVehicleState
{
    public MyVehicle CopiedVehicle { get; private set; }

    public Option<int> EditingId { get; set; }

    public void SetCopiedVehicle(MyVehicle vehicle)
    {
        CopiedVehicle = vehicle;
    }
}

和一個用於檢索車輛的車輛存儲庫

public class MyVehicleRepository
{
    public Option<MyVehicle> GetVehicle(int id)
    {
        return id == 2 ? Some(new MyVehicle("Delorian")) : Option<MyVehicle>.None;
    }
}

如果我想將MyVehicleState中復制的車輛屬性設置為由SelectedVehicleId在同一個 class 中定義的屬性的深層副本,我可以執行以下操作(不確定是否正確):

    var state = new MyVehicleState
    {
        EditingId = Some(2)
    };
    var repo = new MyVehicleRepository();

    state.EditingId
        .Bind(vehicleId => repo.GetVehicle(vehicleId))
        .Map(vehicle => vehicle.DeepCopy())
        .IfSome(copiedVehicle => state.SetCopiedVehicle(copiedVehicle));

現在,如果我將車輛存儲庫更改為異步的,這樣

public class MyVehicleRepository
{
    public async Task<Option<MyVehicle>> GetVehicle(int id)
    {
        await Task.Delay(TimeSpan.FromSeconds(2));
        return id == 2 ? Some(new MyVehicle("Delorian")) : Option<MyVehicle>.None;
    }
}

如何更新我的功能代碼以執行相同的操作並在我的 state class 中設置深層復制?

我已經嘗試切換到BindAsync並使用MapAsync ,但我似乎最終得到了一個我需要解包兩次的輸入並且不確定如何繼續(注意這個功能世界的新手)。

更新

以下似乎可行,但這是最簡潔的方法嗎?

await state.EditingId
        .MapAsync(async vehicleId => await repo.GetVehicle(vehicleId))
        .IfSome(x => x
            .Map(y => y.DeepCopy())
            .IfSome(z => state.SetCopiedVehicle(z)));

如果你想展平一個functor ,那么使用monadic bind。

這是我能想到的最簡單的選擇:

await state.EditingId
    .BindAsync(i => repo.GetVehicle(i).ToAsync())
    .Map(v => v.DeepCopy())
    .Iter(state.SetCopiedVehicle);

ToAsync轉換是必要的,因為它將Task<Option<MyVehicle>>轉換為OptionAsync<MyVehicle> ,隨后的MapIter掛起。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM