C#定義一個Call API並返回Stream的共用方法_參數支援傳入不同物件的彈性設計(依賴倒轉原則DIP)

 

在很久以前有寫過有關SOLID的文章
設計模式特訓_Day01_SOLID五項鐵則


如今在專案偕同過程也遇到實踐機會

假設我今天有一個method想要傳入固定要做
json反序列化成其對應物件的Model Class


這種Model Class可能在專案裡面有一或多個

IC_KeyWord_Model

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;

/// <summary>
/// IC_KeyWord_Model 的摘要描述
/// </summary>
public class IC_KeyWord_Model 
{
    [JsonProperty(PropertyName = "keyword")]
    public string keyword { get; set; }
    [JsonProperty(PropertyName = "similar words")]
    public string[] similarwords { get; set; }
    [JsonProperty(PropertyName = "additional words")]
    public string[] additionalwords { get; set; }

}



IC_RcmdAssg_Model

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;


/// <summary>
/// IC_AssigneeList_Model 的摘要描述
/// </summary>
public class IC_RcmdAssg_Model 
{
    public Assignee_List[] assignee_list { get; set; }
    public int rtnc { get; set; }
}

public class Assignee_List
{
    public string oriAssgName { get; set; }
    public string oriAssgCountry { get; set; }
    public string rcmdName { get; set; }
    public string rcmdCountry { get; set; }
}






這時你會去針對不同物件傳入型態都寫作同樣方法的物件嗎
然後專案裡面這支Class都是一堆重複做同樣事情的method
差別只在於傳入的參數物件型態?







這時就要用到  SOLID當中的Dependency Inversion Principle(DIP)
高層模組不該依賴低層模組(Class....)。
-->換言之,外部在調用的區塊(可能是你的main或多個程式檔案、其他的方法、函數當中)
不該頻繁修改。
兩者(高低層模組)皆應該依賴其抽象,抽象不該依賴細節,細節應該依賴抽象。
在白話一點說,就是實例化的Class之間不發生依賴關係,其依賴關係
透過Interface或Abstract來產生。





一個生活實例:
假設今天某一間公司開的職缺要找一個日文翻譯的人
不可能說限定台大日文或輔仁日文、東吳日文、.....
因為這樣會導致不好招到人且資格範圍太限縮
而是找一個通過某個具有公信力日文檢定、認證。



Interface 就有點類似通過某個認證具有某個資格的涵義
而具體每個人各自是怎麼通過該項認證的都有下不同的苦功。
,公司應徵職務的人不在乎只看你有無拿到該認證資格而已



定義IApiModel介面

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

/// <summary>
/// IApiModel 的摘要描述
/// </summary>
public interface IApiModel
{    
    object DeserializObj(System.IO.StreamReader sr);
}

公用方法中定義要進去的參數寫的是一種資格
只要有實作IApiModel介面的物件都有資格傳入

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net;
using System.Text;
using System.IO;
using Newtonsoft.Json;

/// <summary>
/// HttpHelper 的摘要描述
/// </summary>
public class HttpHelper
{
    public HttpHelper()
    {
        //
        // TODO: 在這裡新增建構函式邏輯
        //
    }



    public static object SendHttpRequest(string requestURI, 
                                         string requestMethod, 
                                         string json, 
                                         string Authorization, 
                                         IApiModel apiModel) //Dependency Inversion Principle(DIP) , 只要是有implement IApiModel中定義的DeserializObj方法的Model Class都可傳入。
    {
        HttpWebRequest request;
        HttpWebResponse response;
        request = (HttpWebRequest)WebRequest.Create(requestURI);
        request.Timeout = 15000;
        request.Method = requestMethod;
        request.ContentType = "application/json";
        request.Headers.Add("charset", "utf-8");
        request.Headers.Add("Authorization", Authorization);
        request.KeepAlive = false;
        byte[] requestBody = Encoding.UTF8.GetBytes(json);
        request.ContentLength = requestBody.Length;
        Stream requestStream = request.GetRequestStream();
        requestStream.Write(requestBody, 0, requestBody.Length);

        response = (HttpWebResponse)request.GetResponse();
        object objResponse = null;
        if (response.StatusCode != HttpStatusCode.OK)
        {
            string tt = response.StatusCode.ToString();
        }
        if (response.GetResponseStream() != null)
        {
            StreamReader myStreamReader = new StreamReader(response.GetResponseStream() ?? Stream.Null, Encoding.UTF8);
            objResponse = apiModel.DeserializObj(myStreamReader);
            myStreamReader.Close();
        }
        return objResponse;
    }


}



實作IApiModel介面的IC_KeyWord_Model

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;

/// <summary>
/// IC_KeyWord_Model 的摘要描述
/// </summary>
public class IC_KeyWord_Model : IApiModel
{
    [JsonProperty(PropertyName = "keyword")]
    public string keyword { get; set; }
    [JsonProperty(PropertyName = "similar words")]
    public string[] similarwords { get; set; }
    [JsonProperty(PropertyName = "additional words")]
    public string[] additionalwords { get; set; }

    public object DeserializObj(StreamReader sr)
    {
        JsonSerializer jsonSerializer = new JsonSerializer();
        return (IC_KeyWord_Model)jsonSerializer.Deserialize(sr, typeof(IC_KeyWord_Model));
    }
}






實作IApiModel介面的IC_RcmdAssg_Model

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;

/// <summary>
/// IC_AssigneeList_Model 的摘要描述
/// </summary>
public class IC_RcmdAssg_Model : IApiModel
{
    public Assignee_List[] assignee_list { get; set; }
    public int rtnc { get; set; }

    public object DeserializObj(StreamReader sr)
    {
        JsonSerializer jsonSerializer = new JsonSerializer();
        return (IC_RcmdAssg_Model)jsonSerializer.Deserialize(sr, typeof(IC_RcmdAssg_Model));
    }
}

public class Assignee_List
{
    public string oriAssgName { get; set; }
    public string oriAssgCountry { get; set; }
    public string rcmdName { get; set; }
    public string rcmdCountry { get; set; }
}














留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

Architecture(架構) 和 Framework(框架) 有何不同?_軟體設計前的事前規劃的藍圖概念

經得起原始碼資安弱點掃描的程式設計習慣培養(五)_Missing HSTS Header