Variant.cs 70 KB

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