iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 19
0
Software Development

如何讓程式碼告訴你他在做什麼?系列 第 20

Day-19 不知不覺就鍊成了!!

  • 分享至 

  • xImage
  •  

接下來繼續前篇未完成的部分

首先是Url,在大多數的狀況下都會是用String來設定

所以就額外加入一個擴充方法叫SetUrl

    public static HttpRequestMessageBuilder SetUrl(
        this HttpRequestMessageBuilder builder,
        string url)
    {
        builder.SetUrl(url.ToUrl());
        return builder;
    }

    internal static Uri ToUrl(this string url)
         => new Uri(url);

再來是HttpMethod,同樣的較多狀況會使用字串來定義

所以同樣也用一個擴充方法來完成

    public static HttpRequestMessageBuilder SetMethod(
        this HttpRequestMessageBuilder builder, 
        string method)
    {
        builder.SetMethod(method.ToHttpMethod());
        return builder;
    }

    internal static HttpMethod ToHttpMethod(this string method)
        => new HttpMethod(method);

接下來Content 比較常見的兩個實作 String 和 Stream 也是各自建立自己的方法

    public static HttpRequestMessageBuilder SetContent(
        this HttpRequestMessageBuilder builder,
        string content)
    {
        builder.SetContent(content.ToHttpContent());
        return builder;
    }

    internal static HttpContent ToHttpContent(this string str)
        => new StringContent(str);

    public static HttpRequestMessageBuilder SetContent(
        this HttpRequestMessageBuilder builder, 
        Stream content)
    {
        builder.SetContent(content.ToHttpContent());
        return builder;
    }

    internal static HttpContent ToHttpContent(this Stream stream)
        => new StreamContent(stream);

Header的內容過多,他甚至可以額外在新建立一組Builder

所以就用前面常用的設定法來完成

    public static HttpRequestMessageBuilder SetHeaderBy(
        this HttpRequestMessageBuilder builder, 
        Action<HttpRequestHeaders> config)
    {
        if(config == null) return builder;

        builder.ConfigureHeader(config);
        return builder;
    }

而最後再用一個輔助的方法來達成讓Builder可以被連續設定

    public static HttpRequestMessageBuilder SetBy(
        this HttpRequestMessageBuilder builder,
        Action<HttpRequestMessageBuilder> config)
    {
        config?.Invoke(builder);
        return builder;
    }

因此,Cralwer引用這樣的方法的方式就會是

    public static Task<IHtmlElementCollection> GetByAsync(
        this ICrawler crawler,
        Action<HttpRequestMessageBuilder> config)
        => crawler.GetAsync(new HttpRequestMessageBuilder()
                .SetBy(config)
                .Build(CreateHttpRequestMessage))
            .ToCollectionsAsync();

所以就可以達成這次主題的目的

    crawler.GetAsync(ConfigureRequest);

    public void ConfigureRequest(HttpRequestMessageBuilder req)
        => req.SetUrl("https://localhost/api")
            .SetMethod("Post")
            .SetContent(JsonConvert.SerializeObject(entitiy))
            .SetHeaderBy(ConfigureRequestHeader);

    public void ConfigureRequestHeader(HttpRequestHeader header)
        =>header.CacheControl
            .SetBy(ConfigureHeaderCacheControl);

    public void ConfigureHeaderCacheControl(CacheControlHeaderValue cache)
        => cache.NoCache = true;

繞了那麼遠,看看是否有達成目標,方法很簡單

跟著程式碼念一次看看對不對就知道了

    // 爬蟲用設定的Request已非同步尋找 html集合 (FindByAsync的 return value)
    crawler.FindByAsync(ConfigureRequest);

    public void ConfigureRequest(HttpRequestMessageBuilder req)
            // 設置url 為 https://localhost/api 
        => req.SetUrl("https://localhost/api")
            // 設置HttpMethod 為 Post
            .SetMethod("Post")
            // 設置內容為 json 序列化 entity 的內容
            .SetContent(JsonConvert.SerializeObject(entitiy))
            // 用 ConfigureRequestHeader來設定 Header
            .SetHeaderBy(ConfigureRequestHeader);

    public void ConfigureRequestHeader(HttpRequestHeader header)
            // 用ConfigureHeaderCacheControl來設定 CacheControl
        =>header.CacheControl.SetBy(ConfigureHeaderCacheControl);

    public void ConfigureHeaderCacheControl(CacheControlHeaderValue cache)
            // 設定cache 的 NoCache為true
        => cache.NoCache = true;

整理文字如下

    內容大綱:
    爬蟲用設定的 Request 已非同步尋找 html 集合 (FindByAsync 的 return value)
    
    內容細節:
    設置 url 為 https://localhost/api 
    設置 HttpMethod 為 Post
    設置內容為 json 序列化 entity 的內容
    用 ConfigureRequestHeader 來設定 Header
    用 ConfigureHeaderCacheControl 來設定 CacheControl
    設定cache 的 NoCache為 true

如此一來外部也可以接得很清楚

備註:


  • 本次範例程式碼以更新至Github
  • 如您目前是團隊工作,則請遵守團隊所訂下的撰寫規範,此篇文章僅為參考建議使用
  • 使用internal的擴充方法的理由是為了避免在使用時造成過多無謂的雜訊 (ex: string 並不是每一個都能轉為url or HttpMethod)
  • 所以同理,想要避免自己開發時造成自己過多的干擾,可以用private
  • SetContent 兩個方法內容雖然一樣,但是實際上他們運作的型別是不同的,利用類似的方式,可以達成不少描述過於複雜的情境(ex:很長的泛型)

上一篇
Day-18 這是兩件事
下一篇
Day-20 在檯面上覆蓋一份測試 結束這回合
系列文
如何讓程式碼告訴你他在做什麼?31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言