其实我也不知道如何定义这个标题,词乏,姑且先这样定义吧。
看了本文章的朋友,如果有更好标题,请告诉我,谢谢。
有个项目使用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 }
如果有更好的方法实现,求指教,谢谢。