通过另类的泛型约束将两个输入输出参数不同的方法合并成一个方法的实现
其实我也不知道如何定义这个标题,词乏,姑且先这样定义吧。
看了本文章的朋友,如果有更好标题,请告诉我,谢谢。
有个项目使用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 }
如果有更好的方法实现,求指教,谢谢。
作者:VAllen
出处:http://www.cnblogs.com/vallen
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
唯有偏执者得以生存。
出处:http://www.cnblogs.com/vallen
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
唯有偏执者得以生存。