/DotNet/Source/ProtoBufRemote/ParameterConverter.cs

https://code.google.com/p/protobuf-remote/ · C# · 385 lines · 329 code · 29 blank · 27 comment · 107 complexity · 266660b3e451ee74365ac443373d0a0a MD5 · raw file

  1. using System;
  2. using System.IO;
  3. using ProtoBuf;
  4. namespace ProtoBufRemote
  5. {
  6. /// <summary>
  7. /// Helper functions for converting parameters to and from protobuf messages. Only public because Reflection Emit
  8. /// generated proxies are technically in a different assembly.
  9. /// </summary>
  10. public static class ParameterConverter
  11. {
  12. /// <summary>
  13. /// Converts a parameter message into an object.
  14. /// </summary>
  15. /// <param name="message"></param>
  16. /// <param name="parameterType"></param>
  17. /// <param name="parameter"></param>
  18. /// <param name="errorMsg"></param>
  19. /// <returns></returns>
  20. public static bool FromMessage(RpcMessage.Parameter message, Type parameterType, out object parameter,
  21. out string errorMsg)
  22. {
  23. if (parameterType.IsPrimitive)
  24. {
  25. if (parameterType == typeof(bool) && message.BoolParamSpecified)
  26. parameter = message.BoolParam;
  27. else if (parameterType == typeof(byte) && message.UintParamSpecified)
  28. parameter = (byte)message.UintParam;
  29. else if (parameterType == typeof(sbyte) && message.IntParamSpecified)
  30. parameter = (sbyte)message.IntParam;
  31. else if (parameterType == typeof(char) && message.UintParamSpecified)
  32. parameter = (char)message.UintParam;
  33. else if (parameterType == typeof(short) && message.IntParamSpecified)
  34. parameter = (short)message.IntParam;
  35. else if (parameterType == typeof(ushort) && message.UintParamSpecified)
  36. parameter = (ushort)message.UintParam;
  37. else if (parameterType == typeof(int) && message.IntParamSpecified)
  38. parameter = message.IntParam;
  39. else if (parameterType == typeof(uint) && message.UintParamSpecified)
  40. parameter = message.UintParam;
  41. else if (parameterType == typeof(long) && message.Int64ParamSpecified)
  42. parameter = message.Int64Param;
  43. else if (parameterType == typeof(ulong) && message.Uint64ParamSpecified)
  44. parameter = message.Uint64Param;
  45. else if (parameterType == typeof(float) && message.FloatParamSpecified)
  46. parameter = message.FloatParam;
  47. else if (parameterType == typeof(double) && message.DoubleParamSpecified)
  48. parameter = message.DoubleParam;
  49. else
  50. {
  51. errorMsg = String.Format("Expected return type '{0}' was not found in the parameter message, or type is not supported. Only integral, string, and protobuf types are supported",
  52. parameterType);
  53. parameter = null;
  54. return false;
  55. }
  56. }
  57. else if (parameterType == typeof(string))
  58. {
  59. if (message.IsNull)
  60. {
  61. parameter = null;
  62. }
  63. else
  64. {
  65. if (!message.StringParamSpecified)
  66. {
  67. errorMsg = String.Format("Expected string return type was not found in the parameter message");
  68. parameter = null;
  69. return false;
  70. }
  71. parameter = message.StringParam;
  72. }
  73. }
  74. else
  75. {
  76. //not a primitive or string, so it must be a protobuf message
  77. object[] attrs = parameterType.GetCustomAttributes(typeof(ProtoContractAttribute), true);
  78. if (attrs.Length < 1)
  79. {
  80. errorMsg = String.Format("Expected return type '{0}' is not supported. Only integral, string, and protobuf types are supported",
  81. parameterType);
  82. parameter = null;
  83. return false;
  84. }
  85. if (message.IsNull)
  86. {
  87. parameter = null;
  88. }
  89. else
  90. {
  91. //check the server returned a protobuf message
  92. if (message.ProtoParam != null)
  93. {
  94. //can't check the protobuf message was the expected type, as protobuf-net is much too lenient, it doesn't
  95. //check required fields or care about invalid fields either
  96. var memStream = new MemoryStream(message.ProtoParam);
  97. parameter = Serializer.NonGeneric.Deserialize(parameterType, memStream);
  98. }
  99. else
  100. {
  101. errorMsg = String.Format("Server had unexpected return type, was expecting a ProtoBuf message of type {0}.",
  102. parameterType);
  103. parameter = null;
  104. return false;
  105. }
  106. }
  107. }
  108. errorMsg = null;
  109. return true;
  110. }
  111. /// <summary>
  112. /// Converts an object to a parameter message.
  113. /// </summary>
  114. /// <param name="parameter"></param>
  115. /// <param name="message"></param>
  116. /// <param name="errorMsg"></param>
  117. /// <returns></returns>
  118. public static bool ToMessage(object parameter, out RpcMessage.Parameter message, out string errorMsg)
  119. {
  120. message = new RpcMessage.Parameter();
  121. if (parameter == null)
  122. {
  123. message.IsNull = true;
  124. }
  125. else
  126. {
  127. if (parameter is string)
  128. message.StringParam = (string)parameter;
  129. else if (parameter is bool)
  130. message.BoolParam = (bool)parameter;
  131. else if (parameter is int)
  132. message.IntParam = (int)parameter;
  133. else if (parameter is uint)
  134. message.UintParam = (uint)parameter;
  135. else if (parameter is float)
  136. message.FloatParam = (float)parameter;
  137. else if (parameter is double)
  138. message.DoubleParam = (double)parameter;
  139. else if (parameter is sbyte)
  140. message.IntParam = (sbyte)parameter;
  141. else if (parameter is byte)
  142. message.UintParam = (byte)parameter;
  143. else if (parameter is char)
  144. message.UintParam = (char)parameter;
  145. else if (parameter is short)
  146. message.IntParam = (short)parameter;
  147. else if (parameter is ushort)
  148. message.UintParam = (ushort)parameter;
  149. else if (parameter is long)
  150. message.Int64Param = (long)parameter;
  151. else if (parameter is ulong)
  152. message.Uint64Param = (ulong)parameter;
  153. else
  154. {
  155. //Must be a protobuf message
  156. Type parameterType = parameter.GetType();
  157. object[] attrs = parameterType.GetCustomAttributes(typeof(ProtoContractAttribute), true);
  158. if (attrs.Length < 1)
  159. {
  160. errorMsg = String.Format("Parameter of type '{0}' is not supported. Only integral, string, and protobuf types are supported",
  161. parameterType);
  162. return false;
  163. }
  164. var memStream = new MemoryStream();
  165. Serializer.NonGeneric.Serialize(memStream, parameter);
  166. message.ProtoParam = memStream.ToArray();
  167. }
  168. }
  169. errorMsg = null;
  170. return true;
  171. }
  172. public static bool IsSupportedType(Type paramType)
  173. {
  174. if (paramType.IsPrimitive && paramType != typeof(decimal))
  175. return true;
  176. if (paramType == typeof(string))
  177. return true;
  178. object[] attrs = paramType.GetCustomAttributes(typeof(ProtoContractAttribute), true);
  179. if (attrs.Length >= 1)
  180. return true;
  181. return false;
  182. }
  183. public static RpcMessage.Parameter IntToMessage(int parameter)
  184. {
  185. var message = new RpcMessage.Parameter();
  186. message.IntParam = parameter;
  187. return message;
  188. }
  189. public static RpcMessage.Parameter UintToMessage(uint parameter)
  190. {
  191. var message = new RpcMessage.Parameter();
  192. message.UintParam = parameter;
  193. return message;
  194. }
  195. public static RpcMessage.Parameter Int64ToMessage(long parameter)
  196. {
  197. var message = new RpcMessage.Parameter();
  198. message.Int64Param = parameter;
  199. return message;
  200. }
  201. public static RpcMessage.Parameter Uint64ToMessage(ulong parameter)
  202. {
  203. var message = new RpcMessage.Parameter();
  204. message.Uint64Param = parameter;
  205. return message;
  206. }
  207. public static RpcMessage.Parameter BoolToMessage(bool parameter)
  208. {
  209. var message = new RpcMessage.Parameter();
  210. message.BoolParam = parameter;
  211. return message;
  212. }
  213. public static RpcMessage.Parameter FloatToMessage(float parameter)
  214. {
  215. var message = new RpcMessage.Parameter();
  216. message.FloatParam = parameter;
  217. return message;
  218. }
  219. public static RpcMessage.Parameter DoubleToMessage(double parameter)
  220. {
  221. var message = new RpcMessage.Parameter();
  222. message.DoubleParam = parameter;
  223. return message;
  224. }
  225. public static RpcMessage.Parameter StringToMessage(string parameter)
  226. {
  227. var message = new RpcMessage.Parameter();
  228. if (parameter == null)
  229. message.IsNull = true;
  230. else
  231. message.StringParam = parameter;
  232. return message;
  233. }
  234. public static RpcMessage.Parameter ProtoToMessage(object parameter)
  235. {
  236. var message = new RpcMessage.Parameter();
  237. if (parameter == null)
  238. {
  239. message.IsNull = true;
  240. }
  241. else
  242. {
  243. var memStream = new MemoryStream();
  244. Serializer.NonGeneric.Serialize(memStream, parameter);
  245. message.ProtoParam = memStream.ToArray();
  246. }
  247. return message;
  248. }
  249. public static bool IntFromMessage(RpcMessage.Parameter message, ref int value, ref string error)
  250. {
  251. if (!message.IntParamSpecified)
  252. {
  253. error = "Parameter did not have expected int type.";
  254. return false;
  255. }
  256. value = message.IntParam;
  257. return true;
  258. }
  259. public static bool UintFromMessage(RpcMessage.Parameter message, ref uint value, ref string error)
  260. {
  261. if (!message.UintParamSpecified)
  262. {
  263. error = "Parameter did not have expected uint type.";
  264. return false;
  265. }
  266. value = message.UintParam;
  267. return true;
  268. }
  269. public static bool Int64FromMessage(RpcMessage.Parameter message, ref long value, ref string error)
  270. {
  271. if (!message.Int64ParamSpecified)
  272. {
  273. error = "Parameter did not have expected long type.";
  274. return false;
  275. }
  276. value = message.Int64Param;
  277. return true;
  278. }
  279. public static bool Uint64FromMessage(RpcMessage.Parameter message, ref ulong value, ref string error)
  280. {
  281. if (!message.Uint64ParamSpecified)
  282. {
  283. error = "Parameter did not have expected ulong type.";
  284. return false;
  285. }
  286. value = message.Uint64Param;
  287. return true;
  288. }
  289. public static bool BoolFromMessage(RpcMessage.Parameter message, ref bool value, ref string error)
  290. {
  291. if (!message.BoolParamSpecified)
  292. {
  293. error = "Parameter did not have expected bool type.";
  294. return false;
  295. }
  296. value = message.BoolParam;
  297. return true;
  298. }
  299. public static bool FloatFromMessage(RpcMessage.Parameter message, ref float value, ref string error)
  300. {
  301. if (!message.FloatParamSpecified)
  302. {
  303. error = "Parameter did not have expected float type.";
  304. return false;
  305. }
  306. value = message.FloatParam;
  307. return true;
  308. }
  309. public static bool DoubleFromMessage(RpcMessage.Parameter message, ref double value, ref string error)
  310. {
  311. if (!message.DoubleParamSpecified)
  312. {
  313. error = "Parameter did not have expected double type.";
  314. return false;
  315. }
  316. value = message.DoubleParam;
  317. return true;
  318. }
  319. public static bool StringFromMessage(RpcMessage.Parameter message, ref string value, ref string error)
  320. {
  321. if (message.IsNull)
  322. {
  323. value = null;
  324. return true;
  325. }
  326. if (!message.StringParamSpecified)
  327. {
  328. error = "Parameter did not have expected string type.";
  329. return false;
  330. }
  331. value = message.StringParam;
  332. return true;
  333. }
  334. public static bool ProtoFromMessage(RpcMessage.Parameter message, Type type, ref object value,
  335. ref string error)
  336. {
  337. if (message.IsNull)
  338. {
  339. value = null;
  340. return true;
  341. }
  342. //check the server returned a protobuf message
  343. if (message.ProtoParam == null)
  344. {
  345. error = String.Format(
  346. "Server had unexpected return type, was expecting a ProtoBuf message of type {0}.", type);
  347. return false;
  348. }
  349. //can't check the protobuf message was the expected type, as protobuf-net is much too lenient, it doesn't
  350. //check required fields or care about invalid fields either
  351. var memStream = new MemoryStream(message.ProtoParam);
  352. value = Serializer.NonGeneric.Deserialize(type, memStream);
  353. return true;
  354. }
  355. }
  356. }