其實我也不知道如何定義這個標題,詞乏,姑且先這樣定義吧。 看了本文章的朋友,如果有更好標題,請告訴我,謝謝。 有個項目使用SDK時遇到這樣一個情況。 該SDK有個BtPrinterManager類,擁有兩個方法:ServerPrint和ClientPrint,這兩個方法有一部分參數是一樣的,一部分參 ...
其實我也不知道如何定義這個標題,詞乏,姑且先這樣定義吧。
看了本文章的朋友,如果有更好標題,請告訴我,謝謝。
有個項目使用SDK時遇到這樣一個情況。
該SDK有個BtPrinterManager類,擁有兩個方法:ServerPrint和ClientPrint,這兩個方法有一部分參數是一樣的,一部分參數不一樣。
現在我們要對這個類進行封裝,把這兩個方法合併成一個方法,並且使其擁有相同的輸入參數和輸出參數。
比較粗糙的做法是,把這兩個方法的輸入參數合併成一個輸入模型類,把兩個方法的輸出參數也合併成一個輸出模型類。
通過增加一個參數或(判斷某個方法專屬參數是否有值)在方法內部決定應該調用ServerPrint還是ClientPrint,以及應該從輸入模型類里取哪些參數,應該賦哪些值給輸出模型類。
如果不按照上面的做法寫,還有什麼辦法可以做到呢?
答案是有的,泛型約束+方法內對泛型實際類型判斷。
以下是實現代碼:
1 using System; 2 3 namespace Test 4 { 5 internal class Program 6 { 7 private static void Main(string[] args) 8 { 9 Run(); 10 11 Console.ReadKey(); 12 } 13 14 private static void Run() 15 { 16 PrinterManager clientManager = new ClientPrinterManager(); 17 ClientInputModel clientInputModel = new ClientInputModel(); 18 //clientInputModel對象賦值.... 19 Action<ClientOutputModel> clientAction = info => { Console.WriteLine(info.PrinterName + info.ClientName); }; 20 clientManager.Print(clientInputModel, clientAction); 21 22 PrinterManager serverManager = new ServerPrinterManager(); 23 ClientInputModel serverInputModel = new ClientInputModel(); 24 //serverInputModel對象賦值.... 25 Action<ServerOutputModel> serverAction = info => { Console.WriteLine(info.PrinterName + info.ServerName); }; 26 serverManager.Print(serverInputModel, serverAction); 27 } 28 } 29 30 /// <summary> 31 /// 列印管理類 32 /// </summary> 33 public abstract class PrinterManager 34 { 35 /// <summary> 36 /// 列印文件 37 /// </summary> 38 /// <typeparam name="TInputModel"></typeparam> 39 /// <typeparam name="TOutputModel"></typeparam> 40 /// <param name="model"></param> 41 /// <param name="action"></param> 42 /// <returns></returns> 43 public abstract string Print<TInputModel, TOutputModel>(TInputModel model, Action<TOutputModel> action) where TInputModel : InputModelBase, new() where TOutputModel : OutputModelBase, new(); 44 } 45 46 /// <summary> 47 /// 客戶端列印管理類 48 /// </summary> 49 public class ClientPrinterManager : PrinterManager 50 { 51 public override string Print<TInputModel, TOutputModel>(TInputModel model, Action<TOutputModel> action) 52 { 53 string message = string.Empty; 54 55 #region 泛型類型校驗 56 if (typeof(TInputModel) != typeof(ClientInputModel)) 57 { 58 throw new ArgumentException($"{nameof(TInputModel)} generic types must be of type {nameof(ClientInputModel)}", nameof(ClientInputModel)); 59 } 60 61 if (typeof(TOutputModel) != typeof(ClientOutputModel)) 62 { 63 throw new ArgumentException($"{nameof(TOutputModel)} generic types must be of type {nameof(ClientOutputModel)}", nameof(ClientOutputModel)); 64 } 65 #endregion 66 67 #region 這裡假裝是調用某SDK方法獲取的結果 68 69 //BtPrinter printer = new BtPrinter(); 70 //string message; 71 //var info = printer.ClientPrint(model.Param1, model.Param2, model.Param1, model.ClientParam1, out message); 72 73 var info = new ClientOutputModel 74 { 75 PrinterName = "Test Printer", 76 ClientName = "Test Client" 77 }; 78 message = "ClientPrint Success"; 79 80 #endregion 81 82 TOutputModel result = (TOutputModel)Convert.ChangeType(info, typeof(TOutputModel)); 83 action(result); 84 85 return message; 86 } 87 } 88 89 /// <summary> 90 /// 伺服器端列印管理類 91 /// </summary> 92 public class ServerPrinterManager : PrinterManager 93 { 94 public override string Print<TInputModel, TOutputModel>(TInputModel model, Action<TOutputModel> action) 95 { 96 string message = string.Empty; 97 98 #region 泛型類型校驗 99 if (typeof(TInputModel) != typeof(ServerInputModel)) 100 { 101 throw new ArgumentException($"{nameof(TInputModel)} generic types must be of type {nameof(ServerInputModel)}", nameof(ServerInputModel)); 102 } 103 104 if (typeof(TOutputModel) != typeof(ServerOutputModel)) 105 { 106 throw new ArgumentException($"{nameof(TOutputModel)} generic types must be of type {nameof(ServerOutputModel)}", nameof(ServerOutputModel)); 107 } 108 #endregion 109 110 #region 這裡假裝是調用某SDK方法獲取的結果 111 112 //BtPrinter printer = new BtPrinter(); 113 //string message; 114 //var info = printer.ServerPrint(model.Param1, model.Param2, model.ServerParam1, model.ServerParam2, out message); 115 116 var info = new ServerOutputModel 117 { 118 PrinterName = "Test Printer", 119 ServerName = "Test Server" 120 }; 121 message = "ServerPrint Success"; 122 123 #endregion 124 125 TOutputModel result = (TOutputModel)Convert.ChangeType(info, typeof(TOutputModel)); 126 action(result); 127 128 return message; 129 } 130 } 131 132 #region 輸入模型類 133 public class InputModelBase 134 { 135 public string Param1 { get; set; } 136 137 public string Param2 { get; set; } 138 } 139 140 public class ClientInputModel : InputModelBase 141 { 142 public string ClientParam1 { get; set; } 143 } 144 145 public class ServerInputModel : InputModelBase 146 { 147 public string ServerParam1 { get; set; } 148 149 public string ServerParam2 { get; set; } 150 } 151 #endregion 152 153 #region 輸出模型類 154 public class OutputModelBase 155 { 156 public string PrinterName { get; set; } 157 } 158 159 public class ClientOutputModel : OutputModelBase 160 { 161 public string ClientName { get; set; } 162 } 163 164 public class ServerOutputModel : OutputModelBase 165 { 166 public string ServerName { get; set; } 167 } 168 #endregion 169 }
如果有更好的方法實現,求指教,謝謝。