精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

告別異常處理:用Result模式和Discriminated Union打造優雅的C#錯誤處理機制

開發 前端
你還有一個中間件可以捕獲所有異常并向用戶返回適當的響應。但過了一段時間后,你決定通過引入Result類型來重構代碼,以避免使用異?!驗楫惓1緫糜谔厥馇闆r。

假設你有一段根據輸入參數返回不同結果的代碼——這很常見。

有幾種方法可以實現這個需求。為了說明我的意思,假設你有以下模型:

public sealed class Note
{
    public Guid Id { get; set; }

    public string Title { get; set; } = null!;

    public Guid UserId { get; set; }

    public DateTimeOffset CreatedAt { get; set; }

    public DateTimeOffset? UpdatedAt { get; set; }
};

這是一個嘗試更新該模型的代碼示例:

public sealed class UpdateNoteHandler(INoteRepository noteRepository)
{
    public async Task InvokeAsync(
        Guid noteId,
        string? title,
        Guid userId)
    {
        var note = await noteRepository.GetNoteOrNullAsync(noteId);

        if (note == null)
        {
            thrownew InvalidOperationException("Note was not found.");
        }

        if (note.UserId != userId)
        {
            thrownew InvalidOperationException("Forbidden.");
        }

        if (string.IsNullOrWhiteSpace(title))
        {
            thrownew InvalidOperationException("Invalid input.");
        }

        note.Title = title;
        note.UpdatedAt = DateTimeOffset.UtcNow;

        await noteRepository.UpdateNoteAsync(note);
    }
}

這個處理程序會為類中定義的每個錯誤拋出異常。

你還有一個中間件可以捕獲所有異常并向用戶返回適當的響應。

但過了一段時間后,你決定通過引入Result類型來重構代碼,以避免使用異常——因為異常本應用于特殊情況。

假設你創建了這樣的東西:

public sealed class Result
{
    public bool IsSuccess => string.IsNullOrWhiteSpace(Error);
    
    public string? Error { get; set; }
}

之后,你將方法更新為這樣:

public sealed class UpdateNoteHandler(INoteRepository noteRepository)
{
    public async Task<Result> InvokeAsync(
        Guid noteId,
        string? title,
        Guid userId)
    {
        var note = await noteRepository.GetNoteOrNullAsync(noteId);

        if (note == null)
        {
            returnnew Result
            {
                Error = "Note was not found."
            };
        }

        if (note.UserId != userId)
        {
            returnnew Result
            {
                Error = "Forbidden."
            };
        }

        if (string.IsNullOrWhiteSpace(title))
        {
            returnnew Result
            {
                Error = "Invalid input."
            };
        }

        note.Title = title;
        note.UpdatedAt = DateTimeOffset.UtcNow;

        await noteRepository.UpdateNoteAsync(note);

        returnnew Result();
    }
}

但目前很難理解每個錯誤代表什么。因此,你希望根據錯誤類型對Result進行分類。

為此,你可能會引入一個ErrorType并像這樣更新Result:

public enum ErrorType
{
    NotFound,
    Forbidden,
    InvalidInput
}

publicsealedclassResult
{
    publicbool IsSuccess => string.IsNullOrWhiteSpace(Error);

    publicstring? Error { get; set; }

    public ErrorType? ErrorType { get; set; }
}

然后,你將方法更新為這樣:

public sealed class UpdateNoteHandler(INoteRepository noteRepository)
{
    public async Task<Result> InvokeAsync(
    Guid noteId,
    string? title,
    Guid userId)
    {
        var note = await noteRepository.GetNoteOrNullAsync(noteId);

        if (note == null)
        {
            returnnew Result
            {
                Error = "Note was not found.",
                ErrorType = ErrorType.NotFound
            };
        }

        if (note.UserId != userId)
        {
            returnnew Result
            {
                Error = "Forbidden.",
                ErrorType = ErrorType.Forbidden
            };
        }

        if (string.IsNullOrWhiteSpace(title))
        {
            returnnew Result
            {
                Error = "Invalid input.",
                ErrorType = ErrorType.InvalidInput
            };
        }

        note.Title = title;
        note.UpdatedAt = DateTimeOffset.UtcNow;

        await noteRepository.UpdateNoteAsync(note);

        returnnew Result();
    }
}

這個方法有效——但只到一定程度。

假設你想為筆記未找到的情況添加一個額外屬性。

但該怎么做?你應該在通用的Result中引入一個新屬性嗎?

像這樣:

public sealed class Result
{
    public bool IsSuccess => string.IsNullOrWhiteSpace(Error);

    public string? Error { get; set; }

    public ErrorType? ErrorType { get; set; }

    public Guid? NoteId { get; set; } // <-- 用于附加數據的新屬性
}

嗯...如果需要添加更多額外數據呢?

這時Result會變得混亂且難以使用——你現在還必須檢查額外數據。

可能會變成這樣:

var result = await hanlder.InvokeAsync();

if(!result.IsSuccess &&
   result.ErrorType == ErrorType.NotFound &&
   result.NoteId.HasValue)
{
    return Results.NoteFound($"There's not such note with id `{result.NoteId.Value}`");
}

這相當煩人——但我很高興告訴你有一個更好的方法來改進這段代碼。

首先,讓我們創建一個Reply類——它將作為我們處理程序結果的基類。

public class Reply;

現在,讓我們為處理程序中的每種情況引入特定的Reply類型:

public sealed class NotFoundReply(Guid noteId) : Reply
{
    public Guid NoteId { get; } = noteId;
}

publicsealedclassForbiddenReply : Reply;

publicsealedclassEmptyTitleReply : Reply;

publicsealedclassSuccessReply : Reply;

如你所見,你的類中不再需要ErrorType枚舉或Error屬性——類型本身已經告訴你服務返回了哪種回復,這非???。

更棒的是,你可以只為特定情況擴展回復類所需的數據——就像NotFoundReply所做的那樣。

很酷,不是嗎?

但讓我們回到我們離開的地方。

現在我要更新我們的處理程序——它將看起來像這樣:

public sealed class UpdateNoteHandler(INoteRepository noteRepository)
{
    public async Task<Reply> InvokeAsync(
        Guid noteId,
        string? title,
        Guid userId)
    {
        var note = await noteRepository.GetNoteOrNullAsync(noteId);

        if (note == null)
        {
            returnnew NotFoundReply(noteId);
        }

        if (note.UserId != userId)
        {
            returnnew ForbiddenReply();
        }

        if (string.IsNullOrWhiteSpace(title))
        {
            returnnew EmptyTitleReply();
        }

        note.Title = title;
        note.UpdatedAt = DateTimeOffset.UtcNow;

        await noteRepository.UpdateNoteAsync(note);

        returnnew SuccessReply();
    }
}

這已經比之前使用Result的方法好多了——但我們還能做得更好。

更好?有什么能比多態方法更好?它有什么問題?

問題在于使用多態方法時,我們無法真正控制具體的類型。任何人都可以輕松添加Reply的新子類,而忘記在代碼中的某處正確處理它。

為了避免這種情況,讓我們引入一個Discriminated Union(可區分聯合),并將我們的Reply重構為DU。

public abstractclassUpdateNoteReply
{
    private UpdateNoeReply()
    {
    }  

    public sealed class NotFoundReply(Guid noteId) : UpdateNoeReply
    {
        public Guid NoteId { get; } = noteId;
    }

    publicsealedclassForbidden : UpdateNoteReply;

    publicsealedclassEmptyTitle : UpdateNoteReply;

    publicsealedclassSuccess : UpdateNoteReply;
}

現在我們獲得了使用Discriminated Union的一些優勢:

? 更容易推理所有可能的狀態

? 設計上就是不可變的

現在你的處理程序將如下所示:

public sealed class UpdateNoteHandler4(INoteRepository noteRepository)
{
    public async Task<UpdateNoteReply> InvokeAsync(
        Guid noteId,
        string? title,
        Guid userId)
    {
        var note = await noteRepository.GetNoteOrNullAsync(noteId);

        if (note == null)
        {
            returnnew UpdateNoteReply.NotFound(noteId);
        }

        if (note.UserId != userId)
        {
            returnnew  UpdateNoteReply.Forbidden();
        }

        if (string.IsNullOrWhiteSpace(title))
        {
            returnnew UpdateNoteReply.EmptyTitle();
        }

        note.Title = title;
        note.UpdatedAt = DateTimeOffset.UtcNow;

        await noteRepository.UpdateNoteAsync(note);

        returnnew UpdateNoteReply.Success();
    }
}

之后,你也可以輕松更新你的端點:

app.MapPost("notes/{id:guid}", async (
    [FromServices] UpdateNoteHandler handler,
    [FromQuery] Guid id) =>
{
    var reply = await handler.InvokeAsync(id, title: "", userId: Guid.Empty);

    return reply switch
    {
        UpdateNoteReply.NotFound notFound => Results.NotFound(notFound.NoteId),
        UpdateNoteReply.EmptyTitle => Results.BadRequest(),
        UpdateNoteReply.Forbidden => Results.Forbid(),
        _ => Results.Ok()
    };
});

通過使用Discriminated Union,我們獲得了:

? 干凈可讀的回復結構

? 能夠使用switch語句

? 僅在真正需要的地方添加額外數據

你怎么看?你在服務中如何返回不同的回復?

責任編輯:武曉燕 來源: 架構師老盧
相關推薦

2021-03-02 09:12:25

Java異常機制

2009-08-05 18:09:17

C#異常處理機制

2009-06-19 16:20:14

ASP.NET錯誤處理

2009-07-31 11:28:42

錯誤處理機制ASP.NET

2011-03-17 09:20:05

異常處理機制

2025-02-10 09:49:00

2009-09-02 18:34:28

C#鼠標事件

2024-03-04 10:00:35

數據庫處理機制

2011-04-06 10:27:46

Java異常處理

2011-07-21 15:20:41

java異常處理機制

2015-12-28 11:25:51

C++異常處理機制

2015-10-09 13:54:14

切面編程錯誤處理機制

2024-04-16 12:18:05

編程異常處理錯誤返回

2021-07-03 17:53:52

Java異常處理機制

2020-12-17 06:25:05

Gopanic 模式

2010-03-05 15:40:16

Python異常

2023-03-08 08:54:59

SpringMVCJava

2021-03-25 07:44:39

C++異常處理開發技術

2021-04-14 07:08:14

Nodejs錯誤處理

2009-08-05 18:28:05

C#異常處理
點贊
收藏

51CTO技術棧公眾號

久久久国产视频| 91久久线看在观草草青青| 成人国产在线激情| 欧美精品一区二区蜜桃| 欧美91在线| 在线观看精品一区| 欧美黄色免费网址| 久久av少妇| 激情五月播播久久久精品| 久久免费精品视频| 亚洲欧美日韩第一页| 精品少妇一区| 91精品国产综合久久久久久 | 在线精品亚洲一区二区不卡| 成年人黄色在线观看| 亚洲av成人精品一区二区三区在线播放 | 亚洲三级在线看| 麻豆成人av| 国产黄色一区二区| 视频一区欧美精品| 国产精品入口麻豆九色| 亚洲字幕在线观看| 午夜视频网站在线观看| 日韩午夜在线| 欧美日本啪啪无遮挡网站| 久久久久亚洲av无码a片| 凹凸成人在线| 4438x亚洲最大成人网| 99久久激情视频| a级大胆欧美人体大胆666| 亚洲欧洲精品一区二区三区不卡| 麻豆av一区二区| 少妇又色又爽又黄的视频| 国产尤物一区二区| 国产精品视频久久久| youjizz在线视频| 亚洲午夜极品| 欧美激情国产高清| 国语对白在线播放| 五月天综合网站| 色婷婷久久av| 任你操精品视频| 精品免费av| 亚洲最新中文字幕| 干b视频在线观看| 免费精品国产| 亚洲精品一区二区网址| 800av在线播放| 成人在线tv视频| 欧美精品一区二区三区蜜桃 | 亚洲大奶少妇| 欧美一区二区三区免费视频| 天天影视色综合| 男人天堂久久| 在线播放91灌醉迷j高跟美女 | 亚洲不卡在线| 精品国产一区二区国模嫣然| 波多野吉衣在线视频| 一区二区三区免费在线看| 欧美sm极限捆绑bd| fc2成人免费视频| 欧美成人专区| 亚洲日本成人网| 丁香激情五月少妇| 欧美韩日一区| 久久国产精品首页| 国产成人精品av久久| 最新日韩欧美| 日韩美女免费线视频| 精人妻无码一区二区三区| 日本中文字幕一区二区有限公司| 国产精品视频一区国模私拍| 一级特黄aaa| 国产精一区二区三区| 激情小说网站亚洲综合网| 日中文字幕在线| 国产精品美女久久久久久久久 | 国产精品美女久久久| 欧美亚洲日本黄色| 中文字幕在线2018| 国产激情偷乱视频一区二区三区| 91老司机福利在线| 国产无套在线观看| 欧美一区二区日韩| 91在线免费看网站| 黄色一级大片在线免费看国产一| www.在线成人| 日韩高清国产精品| 最新日本在线观看| 精品久久在线播放| 亚洲a级黄色片| 精品国产影院| 色妞欧美日韩在线| 国产无套内射又大又猛又粗又爽| 日韩高清国产一区在线| 3d蒂法精品啪啪一区二区免费| 无码国产精品一区二区免费16| 国产色91在线| 欧美成人精品免费| 国产精品亲子伦av一区二区三区| 欧美大片一区二区三区| xxxx日本黄色| 在线成人h网| 国产日韩欧美日韩| 亚洲 欧美 激情 另类| 国产精品美日韩| 欧美一区二区三区爽大粗免费| 成人国产激情| 亚洲国产天堂久久综合| 三级全黄做爰视频| 久久综合图片| 国产伦精品一区二区三区| 秋霞a级毛片在线看| 欧美日韩在线影院| 久久黄色一级视频| 日韩精品午夜| 国产99久久精品一区二区| 亚洲a视频在线| 亚洲欧洲在线观看av| 人妻熟女一二三区夜夜爱| jazzjazz国产精品麻豆| 日韩视频在线免费观看| 无码人妻一区二区三区免费| 不卡视频在线看| 97精品国产97久久久久久| 中文字幕一区二区久久人妻| a在线欧美一区| av中文字幕av| 成人h在线观看| 日韩欧美精品中文字幕| 一级黄色大片免费看| 国产电影一区二区在线观看| 国产成人精品一区二区在线| 桃花色综合影院| 一区二区在线免费观看| 中文字幕 日韩 欧美| 欧美老女人另类| 日韩美女在线看| 六十路在线观看| 一道本成人在线| 国产福利短视频| 亚洲一区国产一区| 精品福利影视| 黄色视屏在线免费观看| 欧美一二三区在线观看| 农村黄色一级片| 国产剧情av麻豆香蕉精品| 国产免费xxx| 国内精品视频| 欧美黑人xxxx| 人妻va精品va欧美va| 亚洲国产日韩a在线播放 | 免费在线观看不卡| 欧美日韩一区二区三区在线观看免| 牛牛精品一区二区| 精品在线欧美视频| 精品黑人一区二区三区| 久久精品视频免费观看| 91色国产在线| 久久亚洲精品中文字幕蜜潮电影| 国产日韩欧美夫妻视频在线观看 | 亚洲亚洲免费| 国产va免费精品高清在线| 成人在线二区| 欧美老人xxxx18| 欧美极品视频在线观看| 成人国产一区二区三区精品| 欧美日韩成人免费视频| 猛男gaygay欧美视频| 国产精品成人av性教育| 久草免费在线观看| 日韩欧美国产精品| 国产精品100| 中文成人av在线| 久久久久亚洲av片无码v| 在线看片一区| 日韩高清国产一区在线观看| 国产高清视频一区二区| 久久久久亚洲精品国产| 欧美精品少妇| 91麻豆精品91久久久久久清纯| 妺妺窝人体色www在线下载| 91在线一区二区三区| 国产一级做a爰片久久| 欧美在线资源| 欧洲亚洲一区二区| 二区三区精品| 57pao国产精品一区| 午夜视频在线免费观看| 亚洲一区二区三区小说| 美女又爽又黄免费| 欧美96一区二区免费视频| 欧美一级中文字幕| 国产99久久精品一区二区300| 91久久久久久久久久久| 在线黄色的网站| 精品国模在线视频| 五月天婷婷在线观看| 欧美另类videos死尸| 99久热在线精品996热是什么| 国产精品对白交换视频| 内射中出日韩无国产剧情| 韩国成人在线视频| 国产成人a亚洲精v品无码| 91精品国产调教在线观看| 久久综合入口| youjizz亚洲| 国产91色在线免费| 超黄网站在线观看| 日韩在线观看高清| 激情小视频在线| 亚洲护士老师的毛茸茸最新章节| 91免费视频播放| 日本韩国视频一区二区| 中文字幕一区二区三区手机版 | 亚洲精品国产欧美| 99热这里只有精品1| 欧美视频一区二区三区四区| 亚洲精品午夜久久久久久久| 樱花影视一区二区| av成人免费网站| 国产精品国产三级国产aⅴ中文| 日本japanese极品少妇| 国产成人精品影视| 中文字幕12页| 美国欧美日韩国产在线播放| 激情网站五月天| 国产精品试看| 秋霞无码一区二区| 欧美激情性爽国产精品17p| 在线观看成人一级片| av中字幕久久| 视频一区视频二区视频三区高| 丝袜美腿综合| 久久久久久久久久久久久久久久av | 国产在线精品一区| 亚洲精品福利| 成人激情av| 伊人精品综合| 超碰97人人人人人蜜桃| 一本一道久久a久久| 超碰在线97av| www.亚洲一二| 国产欧美综合精品一区二区| 一区二区三区在线免费看| 不卡一区二区三区四区五区| 超碰97久久国产精品牛牛| 国产精品久久久久久久久久久久午夜片| 久久久91麻豆精品国产一区| 亚洲一区二区三区视频播放| 麻豆国产一区二区三区四区| 亚洲专区国产精品| 亚洲三级av| 国产91色在线|亚洲| 国产精品白丝av嫩草影院| 国产一区二区三区免费不卡| 欧美久久香蕉| 你懂的视频在线一区二区| 免费一区二区| 亚洲精品视频一二三| 欧美顶级大胆免费视频| 国产精品久久成人免费观看| 你懂的国产精品| 国产美女网站在线观看| 免费视频一区| 污色网站在线观看| 国产精品自在在线| 久久性爱视频网站| 91理论电影在线观看| 欧美激情视频二区| 亚洲欧美电影一区二区| 国产一级一片免费播放放a| 欧美性猛交xxxx乱大交| 在线观看毛片网站| 日韩小视频在线观看专区| 婷婷视频在线观看| 在线观看国产精品91| 亚洲淫性视频| 51色欧美片视频在线观看| 福利一区二区| 成人在线免费观看视视频| 超碰成人在线观看| 日韩一区国产在线观看| 欧美.www| 亚洲人成无码www久久久| 国产一区二区在线观看视频| 久久久久国产精品无码免费看| 国产日韩欧美高清| 久久婷婷综合国产| 欧美在线高清视频| 性生活黄色大片| 亚洲性视频网站| 青草在线视频在线观看| 国产成人avxxxxx在线看| 精品国产鲁一鲁****| 欧美久久电影| 国内激情久久| 污污视频网站免费观看| 成熟亚洲日本毛茸茸凸凹| 成人黄色a级片| 岛国av一区二区三区| 97人妻一区二区精品免费视频| 亚洲精品电影久久久| 黄色av电影在线观看| 欧美在线不卡区| 午夜电影一区| 一区二区日本伦理| 日韩视频在线一区二区三区 | 久久久久久久综合色一本| 日本a级片视频| 在线一区二区三区| 天天综合永久入口| 欧美激情综合色| 欧美高清你懂的| 欧美系列一区| 亚洲精品在线二区| 无码人妻丰满熟妇区毛片蜜桃精品 | 麻豆成人小视频| 伊人久久大香线蕉精品组织观看| 日本三级免费观看| 99久久久免费精品国产一区二区| 四虎永久免费在线| 欧美日韩高清在线| 久青青在线观看视频国产| 国内免费久久久久久久久久久| 99久久这里有精品| 亚洲国产日韩美| 日韩精品电影一区亚洲| 黄色在线观看av| 韩曰欧美视频免费观看| 三级网站在线看| 欧美精品videossex88| 日韩黄色av| 韩国黄色一级大片| 精油按摩中文字幕久久| 亚洲色图 激情小说| 在线观看免费视频综合| 国产在线一二| 国产成人精品日本亚洲专区61| 秋霞蜜臀av久久电影网免费| 人体内射精一区二区三区| 国产成人av网站| 国产在线视频在线观看| 欧美一二区视频| 久草在线视频福利| 999久久久| 欧美成人69av| 图片区偷拍区小说区| 亚洲午夜久久久久久久久电影院| 国产成人久久精品77777综合| 美女精品久久久| 综合伊人久久| 欧美,日韩,国产在线| 久久综合中文字幕| 国产午夜无码视频在线观看| 国产午夜精品一区二区三区| 成人不卡视频| 在线国产伦理一区| 国产一区二区在线视频| 久久无码精品丰满人妻| 亚洲国产另类 国产精品国产免费| 国产无遮挡裸体视频在线观看| 麻豆蜜桃91| 日韩av二区在线播放| 国产男女猛烈无遮挡在线喷水| 欧美性高清videossexo| 麻豆传媒在线完整视频| 俄罗斯精品一区二区| 国产日韩欧美一区在线| 亚洲最大成人综合网| 7878成人国产在线观看| 欧美色图天堂| 精品一区二区三区自拍图片区| 久久xxxx| 杨钰莹一级淫片aaaaaa播放| 亚洲国产免费av| 精品视频在线一区二区在线| 在线视频欧美一区| 成人免费福利片| 国产99久久久久久免费看| 久热精品视频在线观看一区| 精品伊人久久久| 污污网站在线观看视频| 一级日本不卡的影视| 天天色综合久久| 66m—66摸成人免费视频| 精品国产乱码久久久久久蜜坠欲下 | 成人福利视频在线看| 黄色污污网站在线观看| 欧美成人高清视频| 九九视频免费观看视频精品| 国产女同无遮挡互慰高潮91| 精品久久久久人成 | 国语自产在线不卡| 日韩欧美精品| 国产精品扒开腿做爽爽爽a片唱戏| 欧美三级乱人伦电影| 91九色美女在线视频| 中文字幕中文字幕99| 91色九色蝌蚪|