Variant.cs 83 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978
  1. //**************************************
  2. // Name: The Return of the Variant (ver. 6)
  3. // Description:A Variant structure written in C#, ideal for VB.NET 2005 or C# 2002/2003/2005 developers who miss the old (and, in the eyes of many, ugly) VB6 Variant. A Variant is a type that contains any type of variable and can be worked with "automagically" without heavy typecasting procedures. (System.Object is not a variant equivalent because you cannot do things like addition with it.)
  4. // One important difference about this structure: It becomes what you do to it. So if the value is a string and you add an integer of 12, the value becomes an integer. If you want it to remain the same, you should typecast first--for example, add "12" rather than (int)12.
  5. // Changes for v2:
  6. // - All type properties ("String", etc.) are now private.
  7. // - Added implicit/explicit custom operators, so typecasts now work naturally. For example:
  8. // string myString = (string)myVariant; // no longer myVariant.String ...
  9. // float myFloat = (float)myVariant; // no longer myVariant.Float ...
  10. // bool myBool = (bool)myVariant; // no longer myVariant.Boolean ....
  11. // Changes for v3: Quite a few. Added DateTime support. Implemented IConvertible. Changed all the private type name properties to public "To[type]()" methods. Changed the naming convention to conform to IConvertible.
  12. // Changes to v3.1: Removed many unnecessary if statements. Made some documentation updates.
  13. // Changes to v4: Removed the "Type becomes what you do with it" rule for numeric operations. Example: adding an integer of 1 to a float of 1.1 results in a float of 2.1 rather than an integer of 2. Changed operator overloads to automatically adjust the type if the operation causes the resulting value to extend numerically beyond the value of the type. For example, if an integer (Int32) operation results in a value than can fit into an integer, the value is changed to a long (Int64).
  14. // Changes to v5: Changed operator overloads so that if auto-converting to a compatible type, the new type is not smaller than the previous type; Made changes to CBln() to default to True if the object is a non-empty string; Added lots of documentation. Change to v5.1... it's IsNumberable, not IsNumerable. :) Also, To[Type]() should default to the specified type. And SmartMath() method name changed to VariantArithmetic(). Changes in v6... Added TimeSpan type support; added IsDate, IsTimeSpan; updated operator overloads, including equality (==).
  15. // By: Jon Davis
  16. //
  17. //
  18. // Inputs:// Here is an example of use:
  19. // start with a string of "1"
  20. // Variant da = new Variant("1");
  21. // add an integer of 2, becomes 3
  22. // da += 2;
  23. // add a float of 1.3, becomes 4.3
  24. // da += 1.3F;
  25. // add a string, becomes "4.3wow"
  26. // da += "wow";
  27. // writes "4.3wow"
  28. // Console.WriteLine(da);
  29. //
  30. // Returns:None
  31. //
  32. // Assumes:None
  33. //
  34. // Side Effects:Note that as with all typecasting rules, the Variant can be
  35. // dangerous if you are unsure of what you are doing. In this case, the
  36. // Variant class remains strongly typed, while making the most of the CLR's
  37. // intrinsic type conversion features. Conversion of a float (1.5) to an
  38. // integer, for instance, will of course result in data loss. In some cases,
  39. // conversion will simply fail, such as extracting the integer value of the
  40. // string "wow".
  41. // This code is copyrighted and has limited warranties.
  42. // Please see http://www.Planet-Source-Code.com/xq/ASP/txtCodeId.2854/lngWId.10/qx/vb/scripts/ShowCode.htm
  43. // for details.
  44. //**************************************
  45. using System;
  46. namespace FastReport
  47. {
  48. /// <summary>
  49. /// A strongly typed object that readily casts an intrinsic
  50. /// object to the other intrinsic types when possible.
  51. /// </summary>
  52. /// <remarks>
  53. /// <para>The Variant class is an intrinsic object container structure
  54. /// inspired by Visual Basic 6.0's Variant. The key features
  55. /// of a Variant class include the ability to perform typecasts and
  56. /// arithmetic between types that are not normally considered compatible.
  57. /// For example, if a Variant class contains a string describing a
  58. /// number, such as "1.1", then floating point arithmetic can be
  59. /// performed on it.</para>
  60. /// <para>Variants are normally considered dangerous because they
  61. /// strip away the effectiveness of type safety, which is the
  62. /// reason why the Visual Basic 6.0 Variant was left out of
  63. /// Visual Basic .NET. However, this implementation restores the
  64. /// Variant structure, both as a proof of concept and as a
  65. /// restoration of the utility and positive merits of the Variant
  66. /// where it can be used responsibly.</para>
  67. /// </remarks>
  68. #if READONLY_STRUCTS
  69. public readonly struct Variant
  70. #else
  71. public struct Variant
  72. #endif
  73. : IConvertible, IComparable
  74. {
  75. /// <summary>
  76. /// Creates a strongly typed object that readily casts a primitive
  77. /// object to the other primitive types when possible.
  78. /// </summary>
  79. public Variant(object value)
  80. {
  81. if (value == DBNull.Value)
  82. value = null;
  83. if (value != null && value.GetType() == typeof(Variant))
  84. _value = ((Variant)value).Value;
  85. else
  86. _value = value;
  87. }
  88. private readonly object _value;
  89. /// <summary>
  90. /// The actual value being stored in its original <see cref="System.Type"/>,
  91. /// returned as an <see cref="Object"/>.
  92. /// </summary>
  93. public object Value
  94. {
  95. get
  96. {
  97. return this._value;
  98. }
  99. }
  100. /// <summary>
  101. /// The <see cref="System.Type"/> of the <see cref="Value"/> property.
  102. /// </summary>
  103. public Type Type
  104. {
  105. get
  106. {
  107. if (_value == null) return null;
  108. return _value.GetType();
  109. }
  110. }
  111. /// <summary>
  112. /// Returns the <see cref="System.TypeCode"/> for this instance.
  113. /// </summary>
  114. /// <returns>The enumerated constant that is the <see cref="System.TypeCode"/>
  115. /// of the class or value type that implements this interface.</returns>
  116. public TypeCode GetTypeCode()
  117. {
  118. return System.Type.GetTypeCode(this.Type);
  119. }
  120. /// <summary>
  121. /// Returns the string equivalent of the <see cref="Value"/> property.
  122. /// </summary>
  123. private string String
  124. {
  125. get
  126. {
  127. return _value.ToString();
  128. }
  129. }
  130. /// <summary>
  131. /// Attempts to convert or typecast to the specified type.
  132. /// </summary>
  133. /// <param name="type">The type to convert or cast to.</param>
  134. /// <returns>The object after typecasting.</returns>
  135. public object ToType(Type type)
  136. {
  137. return ToType(type, false, null);
  138. }
  139. /// <summary>
  140. /// Attempts to convert or typecast to the specified type.
  141. /// </summary>
  142. /// <param name="type">The type to convert or cast to.</param>
  143. /// <param name="provider">An <see cref="IFormatProvider"/>
  144. /// interface implementation that supplies culture-specific formatting information.</param>
  145. /// <returns>The object after typecasting.</returns>
  146. public object ToType(Type type, IFormatProvider provider)
  147. {
  148. return ToType(type, false, provider);
  149. }
  150. private object ToType(Type type, bool nomap)
  151. {
  152. return ToType(type, nomap, null);
  153. }
  154. private object ToType(Type type, bool nomap, IFormatProvider formatProvider)
  155. {
  156. if (type == this.Type) return _value;
  157. if (!nomap && formatProvider == null)
  158. {
  159. return TypeMap(type);
  160. }
  161. try
  162. {
  163. if (formatProvider != null)
  164. {
  165. return System.Convert.ChangeType(_value, type, formatProvider);
  166. }
  167. else
  168. {
  169. return System.Convert.ChangeType(_value, type);
  170. }
  171. }
  172. catch { }
  173. System.Reflection.MethodInfo[] mis = this.Type.GetMethods();
  174. foreach (System.Reflection.MethodInfo mi in mis)
  175. {
  176. if (mi.Name.ToLower() == "to" + type.Name.ToLower())
  177. {
  178. try
  179. {
  180. if (formatProvider != null && mi.GetParameters().Length == 1)
  181. {
  182. if (mi.GetParameters()[0].ParameterType.IsSubclassOf(typeof(IFormatProvider)))
  183. return mi.Invoke(_value, new object[] { formatProvider });
  184. }
  185. return mi.Invoke(_value, new object[] { });
  186. }
  187. catch { }
  188. }
  189. }
  190. if (!nomap) return TypeMap(type);
  191. throw new InvalidCastException(
  192. "Cannot determine conversion method.");
  193. }
  194. private object TypeMap(Type type)
  195. {
  196. Type tt = type;
  197. if (tt == typeof(System.Boolean))
  198. return this.ToBoolean();
  199. if (tt == typeof(System.String))
  200. return this.ToString();
  201. if (tt == typeof(System.Char))
  202. return this.ToChar();
  203. if (tt == typeof(System.Byte))
  204. return this.ToByte();
  205. if (tt == typeof(System.Int16))
  206. return this.ToInt16();
  207. if (tt == typeof(System.Int32))
  208. return this.ToInt32();
  209. if (tt == typeof(System.Int64))
  210. return this.ToInt64();
  211. if (tt == typeof(System.SByte))
  212. return this.ToSByte();
  213. if (tt == typeof(System.UInt16))
  214. return this.ToUInt16();
  215. if (tt == typeof(System.UInt32))
  216. return this.ToUInt32();
  217. if (tt == typeof(System.UInt64))
  218. return this.ToUInt64();
  219. if (tt == typeof(System.Single))
  220. return this.ToSingle();
  221. if (tt == typeof(System.Double))
  222. return this.ToDouble();
  223. if (tt == typeof(System.Decimal))
  224. return this.ToDecimal();
  225. if (tt == typeof(System.DateTime))
  226. return this.ToDateTime();
  227. if (tt == typeof(System.TimeSpan))
  228. return this.ToTimeSpan();
  229. if (tt == typeof(System.DateTimeOffset))
  230. return this.ToDateTimeOffset();
  231. return ToType(type, true);
  232. }
  233. /// <summary>
  234. /// Returns true if the <see cref="Value"/> property implements <see cref="IConvertible"/>
  235. /// </summary>
  236. public bool ImplementsIConvertible
  237. {
  238. get
  239. {
  240. return Type.IsSubclassOf(typeof(IConvertible));
  241. }
  242. }
  243. /// <summary>
  244. /// Returns true if the <see cref="Value"/> property
  245. /// is a numeric intrinsic value.
  246. /// </summary>
  247. public bool IsNumeric
  248. {
  249. get
  250. {
  251. Type tt = this.Type;
  252. return (tt == typeof(byte) ||
  253. tt == typeof(sbyte) ||
  254. tt == typeof(short) ||
  255. tt == typeof(int) ||
  256. tt == typeof(long) ||
  257. tt == typeof(ushort) ||
  258. tt == typeof(uint) ||
  259. tt == typeof(ulong) ||
  260. tt == typeof(float) ||
  261. tt == typeof(double) ||
  262. tt == typeof(decimal));
  263. }
  264. }
  265. private static readonly char decimalSep = ((float)1.1).ToString().ToCharArray()[1];
  266. /// <summary>
  267. /// Returns true if the <see cref="Value"/> property
  268. /// is a numeric intrinsic value or else can be parsed into
  269. /// a numeric intrinsic value.
  270. /// </summary>
  271. public bool IsNumberable
  272. {
  273. get
  274. {
  275. if (IsNumeric) return true;
  276. Type tt = this.Type;
  277. if (tt == typeof(bool)) return true;
  278. if (tt == typeof(string) ||
  279. tt == typeof(char))
  280. {
  281. try
  282. {
  283. foreach (char c in this.ToString().ToCharArray())
  284. {
  285. if (!char.IsDigit(c) && c != decimalSep) return false;
  286. }
  287. //double d = (this.ToDouble() + (double)0.1);
  288. return true;
  289. }
  290. catch
  291. {
  292. return false;
  293. }
  294. }
  295. return false;
  296. }
  297. }
  298. /// <summary>
  299. /// Returns true if the value is a date or can be parsed into a date.
  300. /// </summary>
  301. public bool IsDate
  302. {
  303. get
  304. {
  305. Type tt = this.Type;
  306. if (tt == typeof(DateTime)) return true;
  307. if (tt == typeof(string))
  308. {
  309. DateTime dt = new DateTime();
  310. if (DateTime.TryParse(this.ToString(), out dt))
  311. return true;
  312. }
  313. return false;
  314. }
  315. }
  316. /// <summary>
  317. /// Returns true if the value is a TimeSpan.
  318. /// </summary>
  319. public bool IsTimeSpan
  320. {
  321. get
  322. {
  323. return this.Type == typeof(TimeSpan);
  324. }
  325. }
  326. /// <summary>
  327. /// If <see cref="Value" /> is a <see cref="System.Boolean"/>, returns
  328. /// as-is. Otherwise, attempts to convert the value of this instance to
  329. /// an equivalent <see cref="System.Boolean"/> value.
  330. /// </summary>
  331. public bool ToBoolean()
  332. {
  333. if (_value == null || _value.ToString() == "") return false;
  334. if (this.Type == typeof(System.Boolean))
  335. return (bool)_value;
  336. return CBln(_value);
  337. }
  338. /// <summary>
  339. /// If <see cref="Value" /> is a <see cref="System.Boolean"/>, returns
  340. /// as-is. Otherwise, attempts to convert the value of this instance to
  341. /// an equivalent <see cref="System.Boolean"/> value using the specified culture-specific
  342. /// formatting information.
  343. /// </summary>
  344. /// <param name="formatProvider">The culture-specific formatting information.</param>
  345. public bool ToBoolean(IFormatProvider formatProvider)
  346. {
  347. return (bool)ToType(typeof(bool), false, formatProvider);
  348. }
  349. /// <summary>
  350. /// If <see cref="Value" /> is a <see cref="System.Byte"/>, returns
  351. /// as-is. Otherwise, attempts to convert the value of this instance
  352. /// to an equivalent 8-bit unsigned integer.
  353. /// </summary>
  354. public byte ToByte()
  355. {
  356. if (_value == null || _value.ToString() == "") return 0;
  357. Type tt = this.Type;
  358. if (tt == typeof(System.Byte))
  359. return (byte)_value;
  360. if (tt == typeof(System.String) || tt == typeof(System.Char))
  361. return byte.Parse(_value.ToString());
  362. if (tt == typeof(System.Boolean))
  363. if ((bool)_value)
  364. return (Byte)1;
  365. else
  366. return (Byte)0;
  367. if (tt == typeof(System.DateTime))
  368. return (byte)((DateTime)_value).Ticks;
  369. if (tt == typeof(System.TimeSpan))
  370. return (byte)((TimeSpan)_value).Ticks;
  371. return (byte)ToType(typeof(byte), true);
  372. }
  373. /// <summary>
  374. /// If <see cref="Value" /> is a <see cref="System.Byte"/>, returns
  375. /// as-is. Otherwise, attempts to convert the value of this instance
  376. /// to an equivalent 8-bit unsigned integer using the specified
  377. /// culture-specific formatting information.
  378. /// </summary>
  379. /// <param name="formatProvider">The culture-specific formatting information.</param>
  380. public byte ToByte(IFormatProvider formatProvider)
  381. {
  382. return (byte)ToType(typeof(byte), false, formatProvider);
  383. }
  384. /// <summary>
  385. /// If <see cref="Value" /> is a <see cref="System.Int16"/>, returns
  386. /// as-is. Otherwise, attempts to convert the value of this instance
  387. /// to an equivalent 16-bit signed integer.
  388. /// </summary>
  389. public short ToInt16()
  390. {
  391. if (_value == null || _value.ToString() == "") return 0;
  392. Type tt = this.Type;
  393. if (tt == typeof(System.Int16))
  394. return (short)_value;
  395. if (tt == typeof(System.String) || tt == typeof(System.Char))
  396. return short.Parse(this._value.ToString());
  397. if (tt == typeof(System.Boolean))
  398. if ((bool)_value)
  399. return (short)1;
  400. else
  401. return (short)0;
  402. if (tt == typeof(System.DateTime))
  403. return (short)((DateTime)_value).Ticks;
  404. if (tt == typeof(System.TimeSpan))
  405. return (short)((TimeSpan)_value).Ticks;
  406. return (short)ToType(typeof(short), true);
  407. }
  408. /// <summary>
  409. /// If <see cref="Value" /> is a <see cref="System.Boolean"/>, returns
  410. /// as-is. Otherwise, attempts to convert the value of this instance to
  411. /// an equivalent 16-bit signed integer using the specified
  412. /// culture-specific formatting information.
  413. /// </summary>
  414. /// <param name="formatProvider">The culture-specific formatting information.</param>
  415. public short ToInt16(IFormatProvider formatProvider)
  416. {
  417. return (short)ToType(typeof(short), false, formatProvider);
  418. }
  419. /// <summary>
  420. /// If <see cref="Value" /> is a <see cref="System.Int32"/>, returns
  421. /// as-is. Otherwise, attempts to convert the value of this instance
  422. /// to an equivalent 32-bit signed integer.
  423. /// </summary>
  424. public int ToInt32()
  425. {
  426. if (_value == null || _value.ToString() == "") return 0;
  427. Type tt = this.Type;
  428. if (tt == typeof(System.Int32))
  429. return (int)_value;
  430. if (tt == typeof(System.String) || tt == typeof(System.Char))
  431. return int.Parse(_value.ToString());
  432. if (tt == typeof(System.Boolean))
  433. if ((bool)_value)
  434. return (int)1;
  435. else
  436. return (int)0;
  437. if (tt == typeof(System.DateTime))
  438. return (int)((DateTime)_value).Ticks;
  439. if (tt == typeof(System.TimeSpan))
  440. return (int)((TimeSpan)_value).Ticks;
  441. return (int)ToType(typeof(int), true);
  442. }
  443. /// <summary>
  444. /// If <see cref="Value" /> is a <see cref="System.Int32"/>, returns
  445. /// as-is. Otherwise, attempts to convert the value of this instance
  446. /// to an equivalent 32-bit signed integer using the specified
  447. /// culture-specific formatting information.
  448. /// </summary>
  449. /// <param name="formatProvider">The culture-specific formatting information.</param>
  450. public int ToInt32(IFormatProvider formatProvider)
  451. {
  452. return (int)ToType(typeof(int), false, formatProvider);
  453. }
  454. /// <summary>
  455. /// If <see cref="Value" /> is a <see cref="System.Int64"/>, returns
  456. /// as-is. Otherwise, attempts to convert the value of this instance
  457. /// to an equivalent 64-bit signed integer.
  458. /// </summary>
  459. public long ToInt64()
  460. {
  461. if (_value == null || _value.ToString() == "") return 0;
  462. Type tt = this.Type;
  463. if (tt == typeof(System.Int64))
  464. return (long)_value;
  465. if (tt == typeof(System.String) || tt == typeof(System.Char))
  466. return long.Parse(_value.ToString());
  467. if (tt == typeof(System.Boolean))
  468. if ((bool)_value)
  469. return (long)1;
  470. else
  471. return (long)0;
  472. if (tt == typeof(System.DateTime))
  473. return (long)((DateTime)_value).Ticks;
  474. if (tt == typeof(System.TimeSpan))
  475. return (long)((TimeSpan)_value).Ticks;
  476. return (long)ToType(typeof(long), true);
  477. }
  478. /// <summary>
  479. /// If <see cref="Value" /> is a <see cref="System.Int64"/>, returns
  480. /// as-is. Otherwise, attempts to convert the value of this instance
  481. /// to an equivalent 64-bit signed integer using the specified
  482. /// culture-specific formatting information.
  483. /// </summary>
  484. /// <param name="formatProvider">The culture-specific formatting information.</param>
  485. public long ToInt64(IFormatProvider formatProvider)
  486. {
  487. return (long)ToType(typeof(long), false, formatProvider);
  488. }
  489. /// <summary>
  490. /// If <see cref="Value" /> is a <see cref="System.Double"/>, returns
  491. /// as-is. Otherwise, attempts to convert the value of this instance
  492. /// to an equivalent double-precision floating-point number.
  493. /// </summary>
  494. public double ToDouble()
  495. {
  496. if (_value == null || _value.ToString() == "") return 0;
  497. Type tt = this.Type;
  498. if (tt == typeof(System.Double))
  499. return (double)_value;
  500. if (tt == typeof(System.String) || tt == typeof(System.Char))
  501. return double.Parse(
  502. _value.ToString());
  503. if (tt == typeof(System.Boolean))
  504. if ((bool)_value)
  505. return (double)1;
  506. else
  507. return (double)0;
  508. if (tt == typeof(System.DateTime))
  509. return (double)((DateTime)_value).Ticks;
  510. if (tt == typeof(System.TimeSpan))
  511. return (double)((TimeSpan)_value).Ticks;
  512. return (double)ToType(typeof(double), true);
  513. }
  514. /// <summary>
  515. /// If <see cref="Value" /> is a <see cref="System.Double"/>, returns
  516. /// as-is. Otherwise, attempts to convert the value of this instance
  517. /// to an equivalent double-precision floating-point number using the
  518. /// specified culture-specific formatting information.
  519. /// </summary>
  520. /// <param name="formatProvider">The culture-specific formatting information.</param>
  521. public double ToDouble(IFormatProvider formatProvider)
  522. {
  523. return (double)ToType(typeof(double), false, formatProvider);
  524. }
  525. /// <summary>
  526. /// If <see cref="Value" /> is a <see cref="System.Single"/>, returns
  527. /// as-is. Otherwise, attempts to convert the value of this instance
  528. /// to an equivalent single-precision floating-point number.
  529. /// </summary>
  530. public float ToSingle()
  531. {
  532. if (_value == null || _value.ToString() == "") return 0;
  533. Type tt = this.Type;
  534. if (tt == typeof(System.Single))
  535. return (float)_value;
  536. if (tt == typeof(System.String) || tt == typeof(System.Char))
  537. return float.Parse(_value.ToString());
  538. if (tt == typeof(System.Boolean))
  539. if ((bool)_value)
  540. return (float)1;
  541. else
  542. return (float)0;
  543. if (tt == typeof(System.DateTime))
  544. return (float)((DateTime)_value).Ticks;
  545. if (tt == typeof(System.TimeSpan))
  546. return (float)((TimeSpan)_value).Ticks;
  547. return (float)ToType(typeof(float), true);
  548. }
  549. /// <summary>
  550. /// If <see cref="Value" /> is a <see cref="System.Single"/>, returns
  551. /// as-is. Otherwise, attempts to convert the value of this instance
  552. /// to an equivalent single-precision floating-point number using the
  553. /// specified culture-specific formatting information.
  554. /// </summary>
  555. /// <param name="formatProvider">The culture-specific formatting information.</param>
  556. public float ToSingle(IFormatProvider formatProvider)
  557. {
  558. return (float)ToType(typeof(float), false, formatProvider);
  559. }
  560. /// <summary>
  561. /// If <see cref="Value" /> is a <see cref="System.Decimal"/>, returns
  562. /// as-is. Otherwise, attempts to convert the value of this instance to
  563. /// an equivalent Decimal number.
  564. /// </summary>
  565. public decimal ToDecimal()
  566. {
  567. if (_value == null || _value.ToString() == "") return 0;
  568. Type tt = this.Type;
  569. if (tt == typeof(System.Decimal))
  570. return (decimal)_value;
  571. if (tt == typeof(System.String) || tt == typeof(System.Char))
  572. return decimal.Parse(_value.ToString());
  573. if (tt == typeof(System.Boolean))
  574. if ((bool)_value)
  575. return (decimal)1;
  576. else
  577. return (decimal)0;
  578. if (tt == typeof(System.DateTime))
  579. return (decimal)((DateTime)_value).Ticks;
  580. if (tt == typeof(System.TimeSpan))
  581. return (decimal)((TimeSpan)_value).Ticks;
  582. return (decimal)ToType(typeof(decimal), true);
  583. }
  584. /// <summary>
  585. /// If <see cref="Value" /> is a <see cref="System.Decimal"/>, returns
  586. /// as-is. Otherwise, attempts to convert the value of this instance to
  587. /// an equivalent Decimal number using the specified culture-specific
  588. /// formatting information.
  589. /// </summary>
  590. /// <param name="formatProvider">The culture-specific formatting information.</param>
  591. public decimal ToDecimal(IFormatProvider formatProvider)
  592. {
  593. return (decimal)ToType(typeof(decimal), false, formatProvider);
  594. }
  595. /// <summary>
  596. /// If <see cref="Value" /> is a <see cref="System.SByte"/>, returns
  597. /// as-is. Otherwise, attempts to convert the value of this instance
  598. /// to an equivalent 8-bit signed integer.
  599. /// </summary>
  600. [CLSCompliant(false)]
  601. public sbyte ToSByte()
  602. {
  603. if (_value == null || _value.ToString() == "") return 0;
  604. Type tt = this.Type;
  605. if (tt == typeof(System.SByte))
  606. return (sbyte)_value;
  607. if (tt == typeof(System.String) || tt == typeof(System.Char))
  608. return sbyte.Parse(_value.ToString());
  609. if (tt == typeof(System.Boolean))
  610. if ((bool)_value)
  611. return (SByte)1;
  612. else
  613. return (SByte)0;
  614. if (tt == typeof(System.DateTime))
  615. return (sbyte)((DateTime)_value).Ticks;
  616. if (tt == typeof(System.TimeSpan))
  617. return (sbyte)((TimeSpan)_value).Ticks;
  618. return (sbyte)ToType(typeof(SByte), true);
  619. }
  620. /// <summary>
  621. /// If <see cref="Value" /> is a <see cref="System.SByte"/>, returns
  622. /// as-is. Otherwise, attempts to convert the value of this instance
  623. /// to an equivalent 8-bit signed integer using the specified
  624. /// culture-specific formatting information.
  625. /// </summary>
  626. /// <param name="formatProvider">The culture-specific formatting information.</param>
  627. [CLSCompliant(false)]
  628. public sbyte ToSByte(IFormatProvider formatProvider)
  629. {
  630. return (sbyte)ToType(typeof(sbyte), false, formatProvider);
  631. }
  632. /// <summary>
  633. /// If <see cref="Value" /> is a <see cref="System.UInt16"/>, returns
  634. /// as-is. Otherwise, attempts to convert the value of this instance
  635. /// to an equivalent 16-bit unsigned integer.
  636. /// </summary>
  637. [CLSCompliant(false)]
  638. public ushort ToUInt16()
  639. {
  640. if (_value == null || _value.ToString() == "") return 0;
  641. Type tt = this.Type;
  642. if (tt == typeof(System.UInt16))
  643. return (ushort)_value;
  644. if (tt == typeof(System.String) || tt == typeof(System.Char))
  645. return ushort.Parse(_value.ToString());
  646. if (tt == typeof(System.Boolean))
  647. if ((bool)_value)
  648. return (ushort)1;
  649. else
  650. return (ushort)0;
  651. if (tt == typeof(System.DateTime))
  652. return (ushort)((DateTime)_value).Ticks;
  653. if (tt == typeof(System.TimeSpan))
  654. return (ushort)((TimeSpan)_value).Ticks;
  655. return (ushort)ToType(typeof(ushort), true);
  656. }
  657. /// <summary>
  658. /// If <see cref="Value" /> is a <see cref="System.UInt16"/>, returns
  659. /// as-is. Otherwise, attempts to convert the value of this instance
  660. /// to an equivalent 16-bit unsigned integer using the specified
  661. /// culture-specific formatting information.
  662. /// </summary>
  663. /// <param name="formatProvider">The culture-specific formatting information.</param>
  664. [CLSCompliant(false)]
  665. public ushort ToUInt16(IFormatProvider formatProvider)
  666. {
  667. return (ushort)ToType(typeof(ushort), false, formatProvider);
  668. }
  669. /// <summary>
  670. /// If <see cref="Value" /> is a <see cref="System.UInt32"/>, returns
  671. /// as-is. Otherwise, attempts to convert the value of this instance
  672. /// to an equivalent 32-bit unsigned integer.
  673. /// </summary>
  674. [CLSCompliant(false)]
  675. public uint ToUInt32()
  676. {
  677. if (_value == null || _value.ToString() == "") return 0;
  678. Type tt = this.Type;
  679. if (tt == typeof(System.UInt32))
  680. return (uint)_value;
  681. if (tt == typeof(System.String) || tt == typeof(System.Char))
  682. return uint.Parse(_value.ToString());
  683. if (tt == typeof(System.Boolean))
  684. if ((bool)_value)
  685. return (uint)1;
  686. else
  687. return (uint)0;
  688. if (tt == typeof(System.DateTime))
  689. return (uint)((DateTime)_value).Ticks;
  690. if (tt == typeof(System.TimeSpan))
  691. return (uint)((TimeSpan)_value).Ticks;
  692. return (uint)ToType(typeof(uint), true);
  693. }
  694. /// <summary>
  695. /// If <see cref="Value" /> is a <see cref="System.UInt32"/>, returns
  696. /// as-is. Otherwise, attempts to convert the value of this instance
  697. /// to an equivalent 32-bit unsigned integer using the specified
  698. /// culture-specific formatting information.
  699. /// </summary>
  700. /// <param name="formatProvider">The culture-specific formatting information.</param>
  701. [CLSCompliant(false)]
  702. public uint ToUInt32(IFormatProvider formatProvider)
  703. {
  704. return (uint)ToType(typeof(uint), false, formatProvider);
  705. }
  706. /// <summary>
  707. /// If <see cref="Value" /> is a <see cref="System.UInt64"/>, returns
  708. /// as-is. Otherwise, attempts to convert the value of this instance
  709. /// to an equivalent 64-bit unsigned integer.
  710. /// </summary>
  711. [CLSCompliant(false)]
  712. public ulong ToUInt64()
  713. {
  714. if (_value == null || _value.ToString() == "") return 0;
  715. Type tt = this.Type;
  716. if (tt == typeof(System.UInt64))
  717. return (ulong)_value;
  718. if (tt == typeof(System.String) || tt == typeof(System.Char))
  719. return ulong.Parse(_value.ToString());
  720. if (tt == typeof(System.Boolean))
  721. if ((bool)_value)
  722. return (ulong)1;
  723. else
  724. return (ulong)0;
  725. if (tt == typeof(System.DateTime))
  726. return (ulong)((DateTime)_value).Ticks;
  727. if (tt == typeof(System.TimeSpan))
  728. return (ulong)((TimeSpan)_value).Ticks;
  729. return (ulong)ToType(typeof(ulong), true);
  730. }
  731. /// <summary>
  732. /// If <see cref="Value" /> is a <see cref="System.UInt64"/>, returns
  733. /// as-is. Otherwise, attempts to convert the value of this instance
  734. /// to an equivalent 64-bit unsigned integer using the specified
  735. /// culture-specific formatting information.
  736. /// </summary>
  737. /// <param name="formatProvider">The culture-specific formatting information.</param>
  738. [CLSCompliant(false)]
  739. public ulong ToUInt64(IFormatProvider formatProvider)
  740. {
  741. return (ulong)ToType(typeof(ulong), false, formatProvider);
  742. }
  743. /// <summary>
  744. /// If <see cref="Value" /> is a <see cref="System.DateTime"/>, returns
  745. /// as-is. Otherwise, attempts to convert the value of this instance to
  746. /// an equivalent DateTime.
  747. /// </summary>
  748. public DateTime ToDateTime()
  749. {
  750. if (_value == null || _value.ToString() == "") return DateTime.MinValue;
  751. Type tt = this.Type;
  752. if (tt == typeof(System.DateTime))
  753. return (DateTime)_value;
  754. if (tt == typeof(System.TimeSpan))
  755. return new DateTime(((TimeSpan)_value).Ticks);
  756. if (tt == typeof(System.String) || tt == typeof(System.Char))
  757. if (this.IsDate)
  758. return DateTime.Parse(_value.ToString());
  759. // if (tt == typeof(System.Boolean))
  760. // throw new InvalidCastException();
  761. if (this.IsNumberable)
  762. return new DateTime(this.ToInt64());
  763. return (DateTime)ToType(typeof(DateTime), true);
  764. }
  765. /// <summary>
  766. /// If <see cref="Value" /> is a <see cref="System.DateTime"/>, returns
  767. /// as-is. Otherwise, attempts to convert the value of this instance to
  768. /// an equivalent DateTime using the specified culture-specific
  769. /// formatting information.
  770. /// </summary>
  771. /// <param name="formatProvider">The culture-specific formatting information.</param>
  772. public DateTime ToDateTime(IFormatProvider formatProvider)
  773. {
  774. return (DateTime)ToType(typeof(DateTime), false, formatProvider);
  775. }
  776. /// <summary>
  777. /// If <see cref="Value" /> is a <see cref="System.TimeSpan"/>, returns
  778. /// as-is. Otherwise, attempts to convert the value of this instance to
  779. /// an equivalent TimeSpan.
  780. /// </summary>
  781. public TimeSpan ToTimeSpan()
  782. {
  783. if (_value == null || _value.ToString() == "") return TimeSpan.MinValue;
  784. Type tt = this.Type;
  785. if (tt == typeof(System.TimeSpan))
  786. return (TimeSpan)_value;
  787. if (tt == typeof(System.DateTime))
  788. return new TimeSpan(((DateTime)_value).Ticks);
  789. if (tt == typeof(System.String) || tt == typeof(System.Char))
  790. if (this.IsDate)
  791. return new TimeSpan(DateTime.Parse(_value.ToString()).Ticks);
  792. // if (tt == typeof(System.Boolean))
  793. // throw new InvalidCastException();
  794. if (this.IsNumberable)
  795. return new TimeSpan(this.ToInt64());
  796. return (TimeSpan)ToType(typeof(TimeSpan), true);
  797. }
  798. /// <summary>
  799. /// If <see cref="Value" /> is a <see cref="System.TimeSpan"/>, returns
  800. /// as-is. Otherwise, attempts to convert the value of this instance to
  801. /// an equivalent TimeSpan using the specified culture-specific
  802. /// formatting information.
  803. /// </summary>
  804. /// <param name="formatProvider">The culture-specific formatting information.</param>
  805. public TimeSpan ToTimeSpan(IFormatProvider formatProvider)
  806. {
  807. return (TimeSpan)ToType(typeof(TimeSpan), false, formatProvider);
  808. }
  809. /// <summary>
  810. /// If <see cref="Value" /> is a <see cref="System.DateTimeOffset"/>, returns
  811. /// as-is. Otherwise, attempts to convert the value of this instance to
  812. /// an equivalent DateTimeOffset.
  813. /// </summary>
  814. public DateTimeOffset ToDateTimeOffset()
  815. {
  816. if (_value == null) return DateTimeOffset.MinValue;
  817. Type tt = this.Type;
  818. if (tt == typeof(DateTimeOffset))
  819. return (DateTimeOffset)_value;
  820. DateTimeOffset result = new DateTimeOffset();
  821. if (DateTimeOffset.TryParse(_value.ToString(), out result))
  822. return result;
  823. return (DateTimeOffset)ToType(typeof(DateTimeOffset), true);
  824. }
  825. /// <summary>
  826. /// If <see cref="Value" /> is a <see cref="System.DateTimeOffset"/>, returns
  827. /// as-is. Otherwise, attempts to convert the value of this instance to
  828. /// an equivalent DateTimeOffset using the specified culture-specific
  829. /// formatting information.
  830. /// </summary>
  831. /// <param name="formatProvider">The culture-specific formatting information.</param>
  832. public DateTimeOffset ToDateTimeOffset(IFormatProvider formatProvider)
  833. {
  834. return (DateTimeOffset)ToType(typeof(DateTimeOffset), false, formatProvider);
  835. }
  836. /// <summary>
  837. /// If <see cref="Value" /> is a <see cref="System.Char"/>, returns
  838. /// as-is. Otherwise, attempts to convert the value of this instance
  839. /// to an equivalent Unicode character.
  840. /// </summary>
  841. public char ToChar()
  842. {
  843. if (_value == null || _value.ToString() == "") return (char)0;
  844. Type tt = this.Type;
  845. if (tt == typeof(System.Char))
  846. return (char)_value;
  847. if (tt == typeof(float) ||
  848. tt == typeof(double) ||
  849. tt == typeof(decimal))
  850. {
  851. return (char)this.ToInt32();
  852. }
  853. if (tt == typeof(System.String))
  854. return char.Parse((string)_value);
  855. if (tt == typeof(System.Boolean))
  856. if ((bool)_value)
  857. return '1';
  858. else
  859. return '0';
  860. try
  861. {
  862. return (char)ToType(typeof(char), true);
  863. }
  864. catch
  865. {
  866. try
  867. {
  868. return char.Parse(_value.ToString());
  869. }
  870. catch
  871. {
  872. try
  873. {
  874. return _value.ToString().ToCharArray()[0];
  875. }
  876. catch { }
  877. }
  878. }
  879. throw new InvalidCastException();
  880. }
  881. /// <summary>
  882. /// If <see cref="Value" /> is a <see cref="System.Char"/>, returns
  883. /// as-is. Otherwise, attempts to convert the value of this instance
  884. /// to an equivalent Unicode character using the specified
  885. /// culture-specific formatting information.
  886. /// </summary>
  887. /// <param name="formatProvider">The culture-specific formatting information.</param>
  888. public char ToChar(IFormatProvider formatProvider)
  889. {
  890. return (Char)ToType(typeof(Char), false, formatProvider);
  891. }
  892. private enum MathAction
  893. {
  894. Add,
  895. Subtract,
  896. Multiply,
  897. Divide,
  898. Modulus,
  899. BitAnd,
  900. BitOr
  901. }
  902. private static object VariantArithmetic(MathAction action, object target, object value)
  903. {
  904. object ret = null;
  905. Variant sv = new Variant(target);
  906. Variant av = new Variant(value);
  907. if (sv.IsNumberable && av.IsNumberable)
  908. {
  909. Double sd = sv.ToDouble();
  910. Double ad = av.ToDouble();
  911. long lsd = (long)sd;
  912. long lad = (long)ad;
  913. System.Type dt = sv.Type;
  914. switch (action)
  915. {
  916. case MathAction.Add:
  917. sd += ad;
  918. break;
  919. case MathAction.Subtract:
  920. sd -= ad;
  921. break;
  922. case MathAction.Multiply:
  923. sd *= ad;
  924. break;
  925. case MathAction.Divide:
  926. sd /= ad;
  927. break;
  928. case MathAction.Modulus:
  929. sd %= ad;
  930. break;
  931. case MathAction.BitAnd:
  932. lsd &= lad;
  933. sd = (double)lsd;
  934. break;
  935. case MathAction.BitOr:
  936. lsd |= lad;
  937. sd = (double)lsd;
  938. break;
  939. }
  940. if (sv.IsNumeric)
  941. {
  942. bool isfloat = (sd != Math.Round(sd, 0));
  943. bool expandminmax = false;
  944. bool expandfloat = false;
  945. bool signed = (
  946. dt == typeof(sbyte) ||
  947. dt == typeof(short) ||
  948. dt == typeof(int) ||
  949. dt == typeof(long) ||
  950. dt == typeof(float) ||
  951. dt == typeof(double) ||
  952. dt == typeof(decimal));
  953. if ((dt == typeof(byte) && (sd < byte.MinValue || sd > byte.MaxValue)) ||
  954. (dt == typeof(sbyte) && (sd < sbyte.MinValue || sd > sbyte.MaxValue)) ||
  955. (dt == typeof(short) && (sd < short.MinValue || sd > short.MaxValue)) ||
  956. (dt == typeof(ushort) && (sd < ushort.MinValue || sd > ushort.MaxValue)) ||
  957. (dt == typeof(int) && (sd < int.MinValue || sd > int.MaxValue)) ||
  958. (dt == typeof(uint) && (sd < uint.MinValue || sd > uint.MaxValue)) ||
  959. (dt == typeof(long) && (sd < long.MinValue || sd > long.MaxValue)) ||
  960. (dt == typeof(ulong) && (sd < ulong.MinValue || sd > ulong.MaxValue)) ||
  961. (dt == typeof(float) && (sd < float.MinValue || sd > float.MaxValue)) ||
  962. (dt == typeof(decimal) && (sd < (double)decimal.MinValue || sd > (double)decimal.MaxValue)))
  963. expandminmax = true;
  964. if (isfloat && (
  965. dt == typeof(byte) ||
  966. dt == typeof(sbyte) ||
  967. dt == typeof(short) ||
  968. dt == typeof(ushort) ||
  969. dt == typeof(int) ||
  970. dt == typeof(uint) ||
  971. dt == typeof(long) ||
  972. dt == typeof(ulong)))
  973. expandfloat = true;
  974. if (expandfloat)
  975. {
  976. /*if (sd < (double)decimal.MinValue || sd > (double)decimal.MaxValue) {
  977. ret = sd;
  978. } else if ((float)sd < (float)float.MinValue || sd > (float)float.MaxValue) {
  979. ret = (decimal)sd;
  980. } else {
  981. ret = (float)sd;
  982. }*/
  983. // do we really need all that stuff above?
  984. // converting to decimal from double makes no sense
  985. // and converting to float from double causing losing precision
  986. // so we just assign value
  987. ret = sd;
  988. }
  989. else if (expandminmax)
  990. {
  991. if (dt == typeof(byte) ||
  992. dt == typeof(sbyte) ||
  993. dt == typeof(short) ||
  994. dt == typeof(ushort) ||
  995. dt == typeof(int) ||
  996. dt == typeof(uint) ||
  997. dt == typeof(long) ||
  998. dt == typeof(ulong))
  999. {
  1000. if (sd < 0 || signed)
  1001. {
  1002. long lmin = long.MinValue;
  1003. long lmax = long.MaxValue;
  1004. if (dt == typeof(sbyte))
  1005. {
  1006. lmin = sbyte.MinValue;
  1007. lmax = sbyte.MaxValue;
  1008. }
  1009. if (dt == typeof(short))
  1010. {
  1011. lmin = short.MinValue;
  1012. lmax = short.MaxValue;
  1013. }
  1014. if (dt == typeof(int))
  1015. {
  1016. lmin = int.MinValue;
  1017. lmax = int.MaxValue;
  1018. }
  1019. if (sd < long.MinValue || sd > long.MaxValue ||
  1020. lmin < long.MinValue || lmax > long.MaxValue)
  1021. {
  1022. ret = sd;
  1023. }
  1024. else if (sd < int.MinValue || sd > int.MaxValue ||
  1025. lmin < int.MinValue || lmax > int.MaxValue)
  1026. {
  1027. ret = (long)sd;
  1028. }
  1029. else if (sd < short.MinValue || sd > short.MaxValue ||
  1030. lmin < short.MinValue || lmax > short.MaxValue)
  1031. {
  1032. ret = (int)sd;
  1033. }
  1034. else if (sd < sbyte.MinValue || sd > sbyte.MaxValue ||
  1035. lmin < sbyte.MinValue || lmax > sbyte.MaxValue)
  1036. {
  1037. ret = (short)sd;
  1038. }
  1039. }
  1040. else
  1041. {
  1042. ulong lmax = ulong.MaxValue;
  1043. if (dt == typeof(byte)) lmax = byte.MaxValue;
  1044. if (dt == typeof(ushort)) lmax = ushort.MaxValue;
  1045. if (dt == typeof(uint)) lmax = uint.MaxValue;
  1046. if (sd < ulong.MinValue || sd > ulong.MaxValue ||
  1047. lmax > ulong.MaxValue)
  1048. {
  1049. ret = sd;
  1050. }
  1051. else if (sd < uint.MinValue || sd > uint.MaxValue ||
  1052. lmax > uint.MaxValue)
  1053. {
  1054. ret = (ulong)sd;
  1055. }
  1056. else if (sd < ushort.MinValue || sd > ushort.MaxValue ||
  1057. lmax > ushort.MaxValue)
  1058. {
  1059. ret = (uint)sd;
  1060. }
  1061. else if (sd < byte.MinValue || sd > byte.MaxValue ||
  1062. lmax > byte.MaxValue)
  1063. {
  1064. ret = (ushort)sd;
  1065. }
  1066. }
  1067. }
  1068. else
  1069. {
  1070. ret = sd;
  1071. }
  1072. }
  1073. else
  1074. { // Not expandfloat and not expandminmax,
  1075. // so revert to original type!
  1076. ret = System.Convert.ChangeType(sd, sv.Type);
  1077. }
  1078. }
  1079. else
  1080. { // not numeric
  1081. Variant v = new Variant(sd);
  1082. ret = v.ToType(sv.Type);
  1083. }
  1084. }
  1085. return ret;
  1086. }
  1087. /// <summary>
  1088. /// Addition operator.
  1089. /// </summary>
  1090. /// <remarks>
  1091. /// If the value on the right is a <see cref="System.String"/>
  1092. /// or a <see cref="System.Char"/>,
  1093. /// the Variant is converted to a string and appended.
  1094. /// If the value on the right or the Variant
  1095. /// is a <see cref="System.DateTime"/>, arithmetic
  1096. /// is performed on the <see cref="DateTime.Ticks"/> property and the
  1097. /// resulting value is set to the DateTime type.
  1098. /// Otherwise, if the value on the right is a number, both
  1099. /// the Variant and the value on the right are
  1100. /// converted to a <see cref="System.Double"/>, the arithmetic
  1101. /// is performed, and the resulting value is converted back to the
  1102. /// original type that the Variant previously represented.
  1103. /// If the type that the Variant previously represented
  1104. /// cannot contain the resulting value--such as if the type is a
  1105. /// <see cref="System.UInt32"/> and the value is <c>-12</c>--then the
  1106. /// type will be converted to a type that can contain
  1107. /// the value, such as <see cref="System.Int32"/>.
  1108. /// </remarks>
  1109. /// <param name="subjectVariant"></param>
  1110. /// <param name="value"></param>
  1111. /// <returns>A new <see cref="Variant"/> containing the resulting value.</returns>
  1112. public static Variant operator +(Variant subjectVariant, object value)
  1113. {
  1114. if (value.GetType() == typeof(Variant))
  1115. value = ((Variant)value).Value;
  1116. Variant sv = subjectVariant; // smaller var name :)
  1117. Variant dv = new Variant(value);
  1118. Type tt = value.GetType();
  1119. if (tt == typeof(bool) && sv.IsNumeric)
  1120. {
  1121. if ((bool)value) value = 1;
  1122. else value = 0;
  1123. tt = value.GetType();
  1124. }
  1125. if (((sv.Type == typeof(string) || sv.Type == typeof(char)) &&
  1126. !sv.IsNumberable) ||
  1127. (tt == typeof(System.String) || tt == typeof(System.Char)))
  1128. return new Variant(sv.ToString() + value.ToString());
  1129. if ((sv.IsDate && dv.IsDate) ||
  1130. (sv.IsDate && dv.IsTimeSpan) || (sv.IsTimeSpan && dv.IsDate) ||
  1131. (sv.IsDate && dv.IsNumberable))
  1132. {
  1133. return new Variant(new DateTime(sv.ToTimeSpan().Ticks + dv.ToTimeSpan().Ticks));
  1134. }
  1135. if (sv.Type == typeof(TimeSpan) && tt == typeof(TimeSpan))
  1136. return new Variant(sv.ToTimeSpan() + dv.ToTimeSpan());
  1137. if (tt == typeof(System.Boolean))
  1138. { // change to boolean and toggle if true
  1139. Variant ret = new Variant(sv.ToBoolean());
  1140. if ((bool)value)
  1141. {
  1142. ret = new Variant(!ret.ToBoolean());
  1143. }
  1144. return ret;
  1145. }
  1146. object retobj = VariantArithmetic(MathAction.Add, sv, value);
  1147. if (retobj != null) return new Variant(retobj);
  1148. throw new InvalidOperationException(
  1149. "Cannot implicitly add value to unidentified type.");
  1150. }
  1151. /// <summary>
  1152. /// Subtraction operator.
  1153. /// </summary>
  1154. /// <remarks>
  1155. /// If the value on the right or the Variant
  1156. /// is a <see cref="System.DateTime"/>, arithmetic
  1157. /// is performed on the <see cref="DateTime.Ticks"/> property and the
  1158. /// resulting value is set to the DateTime type.
  1159. /// Otherwise, if the value on the right is a number, both
  1160. /// the Variant and the value on the right are
  1161. /// converted to a <see cref="System.Double"/>, the arithmetic
  1162. /// is performed, and the resulting value is converted back to the
  1163. /// original type that the Variant previously represented.
  1164. /// If the type that the Variant previously represented
  1165. /// cannot contain the resulting value--such as if the type is a
  1166. /// <see cref="System.UInt32"/> and the value is <c>-12</c>--then the
  1167. /// type will be converted to a type that can contain
  1168. /// the value, such as <see cref="System.Int32"/>.
  1169. /// </remarks>
  1170. /// <param name="subjectVariant"></param>
  1171. /// <param name="value"></param>
  1172. /// <returns>A new <see cref="Variant"/> containing the resulting value.</returns>
  1173. public static Variant operator -(Variant subjectVariant, object value)
  1174. {
  1175. if (value.GetType() == typeof(Variant))
  1176. value = ((Variant)value).Value;
  1177. Variant sv = subjectVariant; // smaller var name :)
  1178. Variant dv = new Variant(value);
  1179. Type tt = value.GetType();
  1180. if (tt == typeof(bool) && sv.IsNumeric)
  1181. {
  1182. if ((bool)value) value = 1;
  1183. else value = 0;
  1184. tt = value.GetType();
  1185. }
  1186. if ((sv.IsDate && dv.IsDate) ||
  1187. (sv.IsDate && dv.IsTimeSpan) || (sv.IsTimeSpan && dv.IsDate) ||
  1188. (sv.IsDate && dv.IsNumberable))
  1189. {
  1190. return new Variant(new DateTime(sv.ToTimeSpan().Ticks - dv.ToTimeSpan().Ticks));
  1191. }
  1192. if (sv.Type == typeof(TimeSpan) && tt == typeof(TimeSpan))
  1193. return new Variant(sv.ToTimeSpan() - dv.ToTimeSpan());
  1194. if (tt == typeof(System.String))
  1195. throw new InvalidOperationException("Objects of type System.ToString() "
  1196. + "cannot subtract.");
  1197. if (tt == typeof(System.Char))
  1198. throw new InvalidOperationException("Objects of type System.ToChar() "
  1199. + "cannot subtract.");
  1200. if (tt == typeof(System.Boolean))
  1201. { // change to boolean and toggle if false
  1202. Variant ret = new Variant(sv.ToBoolean());
  1203. if (!(bool)value)
  1204. {
  1205. ret = new Variant(!ret.ToBoolean());
  1206. }
  1207. return ret;
  1208. }
  1209. object retobj = VariantArithmetic(MathAction.Subtract, sv, value);
  1210. if (retobj != null) return new Variant(retobj);
  1211. throw new InvalidOperationException(
  1212. "Cannot implicitly add value to unidentified type.");
  1213. }
  1214. // AlexTZ
  1215. /// <summary>
  1216. /// Unary minus operator.
  1217. /// </summary>
  1218. public static Variant operator -(Variant subjectVariant)
  1219. {
  1220. return 0 - subjectVariant;
  1221. }
  1222. /// <summary>
  1223. /// Greater than operator.
  1224. /// </summary>
  1225. public static bool operator >(Variant subjectVariant, object value)
  1226. {
  1227. if (value.GetType() == typeof(Variant))
  1228. value = ((Variant)value).Value;
  1229. Variant sv = subjectVariant;
  1230. Variant dv = new Variant(value);
  1231. if (sv.IsNumeric && dv.IsNumeric)
  1232. return sv.ToDouble() > dv.ToDouble();
  1233. if (sv.IsDate && dv.IsDate)
  1234. return sv.ToDateTime() > dv.ToDateTime();
  1235. if (sv.IsTimeSpan && dv.IsTimeSpan)
  1236. return sv.ToTimeSpan() > dv.ToTimeSpan();
  1237. return false;
  1238. }
  1239. /// <summary>
  1240. /// Greater than or equal operator.
  1241. /// </summary>
  1242. public static bool operator >=(Variant subjectVariant, object value)
  1243. {
  1244. return subjectVariant > value || subjectVariant == value;
  1245. }
  1246. /// <summary>
  1247. /// Less than operator.
  1248. /// </summary>
  1249. public static bool operator <(Variant subjectVariant, object value)
  1250. {
  1251. return !(subjectVariant > value || subjectVariant == value);
  1252. }
  1253. /// <summary>
  1254. /// Less than or equal operator.
  1255. /// </summary>
  1256. public static bool operator <=(Variant subjectVariant, object value)
  1257. {
  1258. return !(subjectVariant > value);
  1259. }
  1260. /// <summary>
  1261. /// Multiplication operator.
  1262. /// </summary>
  1263. /// <remarks>
  1264. /// If the value on the right or the Variant
  1265. /// is a <see cref="System.DateTime"/>, arithmetic
  1266. /// is performed on the <see cref="DateTime.Ticks"/> property and the
  1267. /// resulting value is set to the DateTime type.
  1268. /// Otherwise, if the value on the right is a number, both
  1269. /// the Variant and the value on the right are
  1270. /// converted to a <see cref="System.Double"/>, the arithmetic
  1271. /// is performed, and the resulting value is converted back to the
  1272. /// original type that the Variant previously represented.
  1273. /// If the type that the Variant previously represented
  1274. /// cannot contain the resulting value--such as if the type is a
  1275. /// <see cref="System.UInt32"/> and the value is <c>-12</c>--then the
  1276. /// type will be converted to a type that can contain
  1277. /// the value, such as <see cref="System.Int32"/>.
  1278. /// </remarks>
  1279. /// <param name="subjectVariant"></param>
  1280. /// <param name="value"></param>
  1281. /// <returns>A new <see cref="Variant"/> containing the resulting value.</returns>
  1282. public static Variant operator *(Variant subjectVariant, object value)
  1283. {
  1284. if (value.GetType() == typeof(Variant))
  1285. value = ((Variant)value).Value;
  1286. Variant sv = subjectVariant; // smaller var name :)
  1287. Variant dv = new Variant(value);
  1288. Type tt = value.GetType();
  1289. if (tt == typeof(bool) && sv.IsNumeric)
  1290. {
  1291. if ((bool)value) value = 1;
  1292. else value = 0;
  1293. tt = value.GetType();
  1294. }
  1295. if ((sv.IsDate && dv.IsDate) ||
  1296. (sv.IsDate && dv.IsTimeSpan) || (sv.IsTimeSpan && dv.IsDate) ||
  1297. (sv.IsDate && dv.IsNumberable))
  1298. {
  1299. return new Variant(new DateTime(sv.ToTimeSpan().Ticks * dv.ToTimeSpan().Ticks));
  1300. }
  1301. if (sv.Type == typeof(TimeSpan) && tt == typeof(TimeSpan))
  1302. return new Variant(new TimeSpan(sv.ToTimeSpan().Ticks * dv.ToTimeSpan().Ticks));
  1303. if (tt == typeof(System.String))
  1304. throw new InvalidOperationException("Objects of type System.ToString() "
  1305. + "cannot multiply.");
  1306. if (tt == typeof(System.Char))
  1307. throw new InvalidOperationException("Objects of type System.ToChar() "
  1308. + "cannot multiply.");
  1309. if (tt == typeof(System.Boolean))
  1310. { // change to boolean and multiply by 1 (true) or 0 (false)
  1311. Variant ret = new Variant(sv.ToBoolean());
  1312. if (!(bool)value)
  1313. {
  1314. ret = new Variant(!ret.ToBoolean());
  1315. }
  1316. return ret;
  1317. }
  1318. object retobj = VariantArithmetic(MathAction.Multiply, sv, value);
  1319. if (retobj != null) return new Variant(retobj);
  1320. throw new InvalidOperationException(
  1321. "Cannot implicitly add value to unidentified type.");
  1322. }
  1323. /// <summary>
  1324. /// Division operator.
  1325. /// </summary>
  1326. /// <remarks>
  1327. /// If the value on the right or the Variant
  1328. /// is a <see cref="System.DateTime"/>, arithmetic
  1329. /// is performed on the <see cref="DateTime.Ticks"/> property and the
  1330. /// resulting value is set to the DateTime type.
  1331. /// Otherwise, if the value on the right is a number, both
  1332. /// the Variant and the value on the right are
  1333. /// converted to a <see cref="System.Double"/>, the arithmetic
  1334. /// is performed, and the resulting value is converted back to the
  1335. /// original type that the Variant previously represented.
  1336. /// If the type that the Variant previously represented
  1337. /// cannot contain the resulting value--such as if the type is a
  1338. /// <see cref="System.UInt32"/> and the value is <c>-12</c>--then the
  1339. /// type will be converted to a type that can contain
  1340. /// the value, such as <see cref="System.Int32"/>.
  1341. /// </remarks>
  1342. /// <param name="subjectVariant"></param>
  1343. /// <param name="value"></param>
  1344. /// <returns>A new <see cref="Variant"/> containing the resulting value.</returns>
  1345. public static Variant operator /(Variant subjectVariant, object value)
  1346. {
  1347. if (value.GetType() == typeof(Variant))
  1348. value = ((Variant)value).Value;
  1349. Variant sv = subjectVariant; // smaller var name :)
  1350. Variant dv = new Variant(value);
  1351. Type tt = value.GetType();
  1352. if (tt == typeof(bool) && sv.IsNumeric)
  1353. {
  1354. if ((bool)value) value = 1;
  1355. else value = 0;
  1356. tt = value.GetType();
  1357. }
  1358. if ((sv.IsDate && dv.IsDate) ||
  1359. (sv.IsDate && dv.IsTimeSpan) || (sv.IsTimeSpan && dv.IsDate) ||
  1360. (sv.IsDate && dv.IsNumberable))
  1361. {
  1362. return new Variant(new DateTime(sv.ToTimeSpan().Ticks / dv.ToTimeSpan().Ticks));
  1363. }
  1364. if (sv.Type == typeof(TimeSpan) && tt == typeof(TimeSpan))
  1365. return new Variant(new TimeSpan(sv.ToTimeSpan().Ticks / dv.ToTimeSpan().Ticks));
  1366. if (tt == typeof(System.String))
  1367. throw new InvalidOperationException("Objects of type System.ToString() "
  1368. + "cannot divide.");
  1369. if (tt == typeof(System.Char))
  1370. throw new InvalidOperationException("Objects of type System.ToChar() "
  1371. + "cannot divide.");
  1372. if (tt == typeof(System.Boolean))
  1373. {
  1374. throw new InvalidOperationException("Objects of type System.ToChar() "
  1375. + "cannot apply division.");
  1376. }
  1377. object retobj = VariantArithmetic(MathAction.Divide, sv, value);
  1378. if (retobj != null) return new Variant(retobj);
  1379. throw new InvalidOperationException(
  1380. "Cannot implicitly add value to unidentified type.");
  1381. }
  1382. /// <summary>
  1383. /// Modulus operator.
  1384. /// </summary>
  1385. /// <remarks>
  1386. /// If the value on the right or the Variant
  1387. /// is a <see cref="System.DateTime"/>, arithmetic
  1388. /// is performed on the <see cref="DateTime.Ticks"/> property and the
  1389. /// resulting value is set to the DateTime type.
  1390. /// Otherwise, if the value on the right is a number, both
  1391. /// the Variant and the value on the right are
  1392. /// converted to a <see cref="System.Double"/>, the arithmetic
  1393. /// is performed, and the resulting value is converted back to the
  1394. /// original type that the Variant previously represented.
  1395. /// If the type that the Variant previously represented
  1396. /// cannot contain the resulting value--such as if the type is a
  1397. /// <see cref="System.UInt32"/> and the value is <c>-12</c>--then the
  1398. /// type will be converted to a type that can contain
  1399. /// the value, such as <see cref="System.Int32"/>.
  1400. /// </remarks>
  1401. /// <param name="subjectVariant"></param>
  1402. /// <param name="value"></param>
  1403. /// <returns>A new <see cref="Variant"/> containing the resulting value.</returns>
  1404. public static Variant operator %(Variant subjectVariant, object value)
  1405. {
  1406. if (value.GetType() == typeof(Variant))
  1407. value = ((Variant)value).Value;
  1408. Variant sv = subjectVariant; // smaller var name :)
  1409. Variant dv = new Variant(value);
  1410. Type tt = value.GetType();
  1411. if (tt == typeof(bool) && sv.IsNumeric)
  1412. {
  1413. if ((bool)value) value = 1;
  1414. else value = 0;
  1415. tt = value.GetType();
  1416. }
  1417. if ((sv.IsDate && dv.IsDate) ||
  1418. (sv.IsDate && dv.IsTimeSpan) || (sv.IsTimeSpan && dv.IsDate) ||
  1419. (sv.IsDate && dv.IsNumberable))
  1420. {
  1421. return new Variant(new DateTime(sv.ToTimeSpan().Ticks / dv.ToTimeSpan().Ticks));
  1422. }
  1423. if (sv.Type == typeof(TimeSpan) && tt == typeof(TimeSpan))
  1424. return new Variant(new TimeSpan(sv.ToTimeSpan().Ticks % dv.ToTimeSpan().Ticks));
  1425. if (tt == typeof(System.String))
  1426. throw new InvalidOperationException("Objects of type System.ToString() "
  1427. + "cannot apply modulus.");
  1428. if (tt == typeof(System.Char))
  1429. throw new InvalidOperationException("Objects of type System.ToChar() "
  1430. + "cannot apply modulus.");
  1431. if (tt == typeof(System.Boolean))
  1432. throw new InvalidOperationException("Objects of type System.Boolean "
  1433. + "cannot apply modulus.");
  1434. object retobj = VariantArithmetic(MathAction.Modulus, sv, value);
  1435. if (retobj != null) return new Variant(retobj);
  1436. throw new InvalidOperationException(
  1437. "Cannot implicitly add value to unidentified type.");
  1438. }
  1439. /// <summary>
  1440. /// Bitwise And operator.
  1441. /// </summary>
  1442. /// <remarks>
  1443. /// If the value on the right or the Variant
  1444. /// is a <see cref="System.DateTime"/>, arithmetic
  1445. /// is performed on the <see cref="DateTime.Ticks"/> property and the
  1446. /// resulting value is set to the DateTime type.
  1447. /// Otherwise, if the value on the right is a number, both
  1448. /// the Variant and the value on the right are
  1449. /// converted to a <see cref="System.Double"/>, the arithmetic
  1450. /// is performed, and the resulting value is converted back to the
  1451. /// original type that the Variant previously represented.
  1452. /// If the type that the Variant previously represented
  1453. /// cannot contain the resulting value--such as if the type is a
  1454. /// <see cref="System.UInt32"/> and the value is <c>-12</c>--then the
  1455. /// type will be converted to a type that can contain
  1456. /// the value, such as <see cref="System.Int32"/>.
  1457. /// </remarks>
  1458. /// <param name="subjectVariant"></param>
  1459. /// <param name="value"></param>
  1460. /// <returns>A new <see cref="Variant"/> containing the resulting value.</returns>
  1461. public static Variant operator &(Variant subjectVariant, object value)
  1462. {
  1463. if (value.GetType() == typeof(Variant))
  1464. value = ((Variant)value).Value;
  1465. Variant sv = subjectVariant; // smaller var name :)
  1466. Variant dv = new Variant(value);
  1467. Type tt = value.GetType();
  1468. if (tt == typeof(bool) && sv.IsNumeric)
  1469. {
  1470. if ((bool)value) value = 1;
  1471. else value = 0;
  1472. tt = value.GetType();
  1473. }
  1474. if (tt == typeof(System.Single))
  1475. throw new InvalidOperationException("Operator '&' cannot "
  1476. + "be applied to operands of type 'float' and 'float'.");
  1477. if (tt == typeof(System.Double))
  1478. throw new InvalidOperationException("Operator '&' cannot "
  1479. + "be applied to operands of type 'double' and 'double'.");
  1480. if (tt == typeof(System.Decimal))
  1481. throw new InvalidOperationException("Operator '&' cannot "
  1482. + "be applied to operands of type 'decimal' and 'decimal'.");
  1483. if ((sv.IsDate && dv.IsDate) ||
  1484. (sv.IsDate && dv.IsTimeSpan) || (sv.IsTimeSpan && dv.IsDate) ||
  1485. (sv.IsDate && dv.IsNumberable))
  1486. {
  1487. return new Variant(new DateTime(sv.ToTimeSpan().Ticks & dv.ToTimeSpan().Ticks));
  1488. }
  1489. if (sv.Type == typeof(TimeSpan) && tt == typeof(TimeSpan))
  1490. return new Variant(new TimeSpan(sv.ToTimeSpan().Ticks & dv.ToTimeSpan().Ticks));
  1491. if (tt == typeof(System.String))
  1492. throw new InvalidOperationException("Objects of type System.ToString() "
  1493. + "cannot apply '&' operator.");
  1494. if (tt == typeof(System.Char))
  1495. throw new InvalidOperationException("Objects of type System.ToChar() "
  1496. + "cannot apply '&' operator.");
  1497. if (tt == typeof(System.Boolean))
  1498. return new Variant(sv.ToBoolean() & (bool)value);
  1499. object retobj = VariantArithmetic(MathAction.BitAnd, sv, value);
  1500. if (retobj != null) return new Variant(retobj);
  1501. throw new InvalidOperationException(
  1502. "Cannot implicitly add value to unidentified type.");
  1503. }
  1504. /// <summary>
  1505. /// Bitwise Or operator.
  1506. /// </summary>
  1507. /// <remarks>
  1508. /// If the value on the right or the Variant
  1509. /// is a <see cref="System.DateTime"/>, arithmetic
  1510. /// is performed on the <see cref="DateTime.Ticks"/> property and the
  1511. /// resulting value is set to the DateTime type.
  1512. /// Otherwise, if the value on the right is a number, both
  1513. /// the Variant and the value on the right are
  1514. /// converted to a <see cref="System.Double"/>, the arithmetic
  1515. /// is performed, and the resulting value is converted back to the
  1516. /// original type that the Variant previously represented.
  1517. /// If the type that the Variant previously represented
  1518. /// cannot contain the resulting value--such as if the type is a
  1519. /// <see cref="System.UInt32"/> and the value is <c>-12</c>--then the
  1520. /// type will be converted to a type that can contain
  1521. /// the value, such as <see cref="System.Int32"/>.
  1522. /// </remarks>
  1523. /// <param name="subjectVariant"></param>
  1524. /// <param name="value"></param>
  1525. /// <returns>A new <see cref="Variant"/> containing the resulting value.</returns>
  1526. public static Variant operator |(Variant subjectVariant, object value)
  1527. {
  1528. if (value.GetType() == typeof(Variant))
  1529. value = ((Variant)value).Value;
  1530. Variant sv = subjectVariant; // smaller var name :)
  1531. Variant dv = new Variant(value);
  1532. Type tt = value.GetType();
  1533. if (tt == typeof(bool) && sv.IsNumeric)
  1534. {
  1535. if ((bool)value) value = 1;
  1536. else value = 0;
  1537. tt = value.GetType();
  1538. }
  1539. if (tt == typeof(System.Single))
  1540. throw new InvalidOperationException("Operator '|' cannot "
  1541. + "be applied to operands of type 'float' and 'float'.");
  1542. if (tt == typeof(System.Double))
  1543. throw new InvalidOperationException("Operator '|' cannot "
  1544. + "be applied to operands of type 'double' and 'double'.");
  1545. if (tt == typeof(System.Decimal))
  1546. throw new InvalidOperationException("Operator '|' cannot "
  1547. + "be applied to operands of type 'decimal' and 'decimal'.");
  1548. if ((sv.IsDate && dv.IsDate) ||
  1549. (sv.IsDate && dv.IsTimeSpan) || (sv.IsTimeSpan && dv.IsDate) ||
  1550. (sv.IsDate && dv.IsNumberable))
  1551. {
  1552. return new Variant(new DateTime(sv.ToTimeSpan().Ticks | dv.ToTimeSpan().Ticks));
  1553. }
  1554. if ((sv.Type == typeof(TimeSpan) && tt == typeof(TimeSpan)) ||
  1555. (sv.IsNumberable && tt == typeof(TimeSpan)) ||
  1556. (sv.Type == typeof(TimeSpan) && dv.IsNumberable))
  1557. return new Variant(new TimeSpan(sv.ToTimeSpan().Ticks | dv.ToTimeSpan().Ticks));
  1558. if (tt == typeof(System.String))
  1559. throw new InvalidOperationException("Objects of type System.ToString() "
  1560. + "cannot apply '|' operator.");
  1561. if (tt == typeof(System.Char))
  1562. throw new InvalidOperationException("Objects of type System.ToChar() "
  1563. + "cannot apply '|' operator.");
  1564. if (tt == typeof(System.Boolean))
  1565. return new Variant(sv.ToBoolean() | (bool)value);
  1566. object retobj = VariantArithmetic(MathAction.BitOr, sv, value);
  1567. if (retobj != null) return new Variant(retobj);
  1568. throw new InvalidOperationException(
  1569. "Cannot implicitly add value to unidentified type.");
  1570. }
  1571. /// <summary>
  1572. /// Inequality operator.
  1573. /// </summary>
  1574. /// <param name="subjectVariant"></param>
  1575. /// <param name="value"></param>
  1576. /// <returns>
  1577. /// The opposite of ==
  1578. /// </returns>
  1579. public static bool operator !=(Variant subjectVariant, object value)
  1580. {
  1581. return !(subjectVariant == value);
  1582. }
  1583. /// <summary>
  1584. /// <para>Equality operator.</para>
  1585. /// <para>First attempts to compare the left value after
  1586. /// temporarily converting it to the type of the right value.
  1587. /// If the conversion cannot occur, such as if the value is not an
  1588. /// intrinsic value type, the comparison occurs at the <see cref="System.Object"/>
  1589. /// level using <b>Object.Equals</b>.</para>
  1590. /// </summary>
  1591. /// <param name="subjectVariant"></param>
  1592. /// <param name="value"></param>
  1593. /// <returns></returns>
  1594. public static bool operator ==(Variant subjectVariant, object value)
  1595. {
  1596. if (value.GetType() == typeof(Variant))
  1597. value = ((Variant)value).Value;
  1598. Variant sv = subjectVariant; // smaller var name :)
  1599. Variant dv = new Variant(value);
  1600. Variant dvv = dv;
  1601. if (sv.IsNumberable && dv.IsNumberable)
  1602. {
  1603. sv = new Variant(sv.ToDouble());
  1604. dvv = new Variant(dv.ToDouble());
  1605. }
  1606. //if (sv.Type != dvv.Type) return false;
  1607. if (sv.IsDate && dv.IsDate)
  1608. return sv.ToDateTime() == dv.ToDateTime();
  1609. if (sv.IsTimeSpan && dv.IsTimeSpan)
  1610. return sv.ToTimeSpan() == dvv.ToTimeSpan();
  1611. Type tt = dvv.Type;
  1612. if (tt == typeof(System.String) || tt == typeof(System.Char))
  1613. if (sv.ToString() == dvv.ToString()) return true;
  1614. if (dv.IsNumeric)
  1615. return sv.ToDouble() == dv.ToDouble();
  1616. if (dv.Type == typeof(System.Boolean))
  1617. return sv.ToBoolean() == (bool)value;
  1618. return sv.Value == dv.Value;//Object.Equals(subjectVariant.Value, value);
  1619. }
  1620. /// <summary>
  1621. /// <para>Equality operator.</para>
  1622. /// </summary>
  1623. /// <param name="subjectVariant"></param>
  1624. /// <param name="value"></param>
  1625. /// <returns></returns>
  1626. public static bool operator ==(Variant subjectVariant, string value)
  1627. {
  1628. return subjectVariant.ToString() == value;
  1629. }
  1630. /// <summary>
  1631. /// <para>Equality operator.</para>
  1632. /// </summary>
  1633. /// <param name="subjectVariant"></param>
  1634. /// <param name="value"></param>
  1635. /// <returns></returns>
  1636. public static bool operator !=(Variant subjectVariant, string value)
  1637. {
  1638. return subjectVariant.ToString() != value;
  1639. }
  1640. /// <summary>
  1641. /// Returns <see cref="String"/> property unless the value on the right
  1642. /// is null. If the value on the right is null, returns "".
  1643. /// </summary>
  1644. /// <returns></returns>
  1645. public override string ToString()
  1646. {
  1647. if (_value == null || _value.ToString() == "") return "";
  1648. return this.String;
  1649. }
  1650. /// <summary>
  1651. /// Converts the value of this instance to an equivalent <see cref="String"/>
  1652. /// using the specified culture-specific formatting information.
  1653. /// </summary>
  1654. /// <param name="formatProvider"></param>
  1655. /// <returns></returns>
  1656. public string ToString(IFormatProvider formatProvider)
  1657. {
  1658. return (string)ToType(typeof(string), false, formatProvider);
  1659. }
  1660. /// <summary>
  1661. /// See <see cref="Object.GetHashCode()"/>.
  1662. /// </summary>
  1663. /// <returns></returns>
  1664. public override int GetHashCode()
  1665. {
  1666. return base.GetHashCode();
  1667. }
  1668. /// <summary>
  1669. /// See <see cref="Object.Equals(object)"/>.
  1670. /// </summary>
  1671. /// <param name="obj"></param>
  1672. /// <returns></returns>
  1673. public override bool Equals(object obj)
  1674. {
  1675. return base.Equals(obj);
  1676. }
  1677. /// <summary>
  1678. /// Converts an object to a boolean.
  1679. /// For any type, if null, returns false.
  1680. /// For Boolean: true/false.
  1681. /// For String: "", "false", "0", etc. == false;
  1682. /// "1", "true", etc. == true, else true.
  1683. /// For numeric intrinsics: 0 == false, else true.
  1684. /// For any other non-null object, returns true.
  1685. /// </summary>
  1686. /// <param name="bln">The string to be converted</param>
  1687. /// <returns>The boolean value of this string.</returns>
  1688. public static bool CBln(object bln)
  1689. {
  1690. if (bln == null) return false;
  1691. if (bln.GetType() == typeof(bool))
  1692. {
  1693. return (bool)bln;
  1694. }
  1695. else if (bln.GetType() == typeof(string))
  1696. {
  1697. string val = (string)bln;
  1698. bool ret = true;
  1699. val = val.ToLower().Trim();
  1700. string sTrue = true.ToString().ToLower();
  1701. string sFalse = false.ToString().ToLower();
  1702. if (val == "" ||
  1703. val == "false" ||
  1704. val == "f" ||
  1705. val == "0" ||
  1706. val == "no" ||
  1707. val == "n" ||
  1708. val == "off" ||
  1709. val == "negative" ||
  1710. val == "neg" ||
  1711. val == "disabled" ||
  1712. val == "incorrect" ||
  1713. val == "wrong" ||
  1714. val == "left" ||
  1715. val == sFalse)
  1716. {
  1717. ret = false;
  1718. return ret;
  1719. }
  1720. if (val == "true" ||
  1721. val == "t" ||
  1722. val == "1" ||
  1723. val == "-1" ||
  1724. val == "yes" ||
  1725. val == "y" ||
  1726. val == "positive" ||
  1727. val == "pos" ||
  1728. val == "on" ||
  1729. val == "enabled" ||
  1730. val == "correct" ||
  1731. val == "right" ||
  1732. val == sTrue)
  1733. {
  1734. ret = true;
  1735. return ret;
  1736. }
  1737. try
  1738. {
  1739. ret = bool.Parse(val);
  1740. }
  1741. catch { }
  1742. return ret;
  1743. }
  1744. else if (bln.GetType() == typeof(byte) ||
  1745. bln.GetType() == typeof(ushort) ||
  1746. bln.GetType() == typeof(decimal) ||
  1747. bln.GetType() == typeof(sbyte) ||
  1748. bln.GetType() == typeof(ulong) ||
  1749. bln.GetType() == typeof(int) ||
  1750. bln.GetType() == typeof(uint) ||
  1751. bln.GetType() == typeof(long) ||
  1752. bln.GetType() == typeof(short) ||
  1753. bln.GetType() == typeof(double) ||
  1754. bln.GetType() == typeof(float))
  1755. {
  1756. if (bln.ToString() != "0" && bln.ToString() != "0.0")
  1757. {
  1758. return true;
  1759. }
  1760. else
  1761. {
  1762. return false;
  1763. }
  1764. }
  1765. return true;
  1766. }
  1767. public int CompareTo(object other)
  1768. {
  1769. if (this > other) return 1;
  1770. else if (this == other) return 0;
  1771. else return -1;
  1772. }
  1773. // AlexTZ
  1774. ///
  1775. public static implicit operator string(Variant v)
  1776. {
  1777. return v.ToString();
  1778. }
  1779. ///
  1780. public static implicit operator Variant(string v)
  1781. {
  1782. return new Variant(v);
  1783. }
  1784. ///
  1785. public static implicit operator char(Variant v)
  1786. {
  1787. return v.ToChar();
  1788. }
  1789. ///
  1790. public static implicit operator Variant(char v)
  1791. {
  1792. return new Variant(v);
  1793. }
  1794. ///
  1795. public static implicit operator byte(Variant v)
  1796. {
  1797. return v.ToByte();
  1798. }
  1799. ///
  1800. public static implicit operator Variant(byte v)
  1801. {
  1802. return new Variant(v);
  1803. }
  1804. ///
  1805. [CLSCompliant(false)]
  1806. public static implicit operator sbyte(Variant v)
  1807. {
  1808. return v.ToSByte();
  1809. }
  1810. ///
  1811. [CLSCompliant(false)]
  1812. public static implicit operator Variant(sbyte v)
  1813. {
  1814. return new Variant(v);
  1815. }
  1816. ///
  1817. public static implicit operator short(Variant v)
  1818. {
  1819. return v.ToInt16();
  1820. }
  1821. ///
  1822. public static implicit operator Variant(short v)
  1823. {
  1824. return new Variant(v);
  1825. }
  1826. ///
  1827. [CLSCompliant(false)]
  1828. public static implicit operator ushort(Variant v)
  1829. {
  1830. return v.ToUInt16();
  1831. }
  1832. ///
  1833. [CLSCompliant(false)]
  1834. public static implicit operator Variant(ushort v)
  1835. {
  1836. return new Variant(v);
  1837. }
  1838. ///
  1839. public static implicit operator int(Variant v)
  1840. {
  1841. return v.ToInt32();
  1842. }
  1843. ///
  1844. public static implicit operator Variant(int v)
  1845. {
  1846. return new Variant(v);
  1847. }
  1848. ///
  1849. [CLSCompliant(false)]
  1850. public static implicit operator uint(Variant v)
  1851. {
  1852. return v.ToUInt32();
  1853. }
  1854. ///
  1855. [CLSCompliant(false)]
  1856. public static implicit operator Variant(uint v)
  1857. {
  1858. return new Variant(v);
  1859. }
  1860. ///
  1861. public static implicit operator long(Variant v)
  1862. {
  1863. return v.ToInt64();
  1864. }
  1865. ///
  1866. public static implicit operator Variant(long v)
  1867. {
  1868. return new Variant(v);
  1869. }
  1870. ///
  1871. [CLSCompliant(false)]
  1872. public static implicit operator ulong(Variant v)
  1873. {
  1874. return v.ToUInt64();
  1875. }
  1876. ///
  1877. [CLSCompliant(false)]
  1878. public static implicit operator Variant(ulong v)
  1879. {
  1880. return new Variant(v);
  1881. }
  1882. ///
  1883. public static implicit operator float(Variant v)
  1884. {
  1885. return v.ToSingle();
  1886. }
  1887. ///
  1888. public static implicit operator Variant(float v)
  1889. {
  1890. return new Variant(v);
  1891. }
  1892. ///
  1893. public static implicit operator double(Variant v)
  1894. {
  1895. return v.ToDouble();
  1896. }
  1897. ///
  1898. public static implicit operator Variant(double v)
  1899. {
  1900. return new Variant(v);
  1901. }
  1902. ///
  1903. public static implicit operator decimal(Variant v)
  1904. {
  1905. return v.ToDecimal();
  1906. }
  1907. ///
  1908. public static implicit operator Variant(decimal v)
  1909. {
  1910. return new Variant(v);
  1911. }
  1912. ///
  1913. public static implicit operator bool(Variant v)
  1914. {
  1915. return v.ToBoolean();
  1916. }
  1917. ///
  1918. public static implicit operator Variant(bool v)
  1919. {
  1920. return new Variant(v);
  1921. }
  1922. ///
  1923. public static implicit operator DateTime(Variant v)
  1924. {
  1925. return v.ToDateTime();
  1926. }
  1927. ///
  1928. public static implicit operator Variant(DateTime v)
  1929. {
  1930. return new Variant(v);
  1931. }
  1932. ///
  1933. public static implicit operator TimeSpan(Variant v)
  1934. {
  1935. return v.ToTimeSpan();
  1936. }
  1937. ///
  1938. public static implicit operator Variant(TimeSpan v)
  1939. {
  1940. return new Variant(v);
  1941. }
  1942. }
  1943. }