Some helper methods … extension methods …

17 Mar 2009

In this post, I would like to document a couple of classes with several methods that are useful to convert from one type of data to another. For example, some of the methods can be used to convert a Dataset into JSON string and vice versa.

SQL Query output as XML

The first class to start with the most simplest one. This class can be used to wrap your SQL queries for Sql Server or Oracle such that they return XML output instead of rows. Strategy pattern has been used to implement these methods – nothing fancy.

The base class for query wrapper.

   1: public abstract class QueryWrapper


   2: {


   3:     public abstract string ForXmlOutput(string query);


   4: }




Then one wrapper each for Sql and Oracle has been implemented as shown.





   1: public class SqlQueryWrapper : QueryWrapper


   2: {


   3:     public override string ForXmlOutput(string query)


   4:     {


   5:         return (string.Format("{0} FOR XML RAW;", query)).Trim();


   6:     }


   7: }


   8:  


   9: public class OracleQueryWrapper : QueryWrapper


  10: {


  11:     public override string ForXmlOutput(string query)


  12:     {


  13:         return string.Format("SELECT DBMS_XMLGEN.getXML(\"{0}\",0) from dual;", query);


  14:     }


  15: }




And then there is services class that uses strategy pattern.





   1: public class WrapperServices


   2: {


   3:     private QueryWrapper _wrapper;


   4:     public WrapperServices(QueryWrapper wrapper)


   5:     {


   6:         this._wrapper = wrapper;


   7:     }


   8:  


   9:     public string WrapQueryForXml(string query)


  10:     {


  11:         return _wrapper.ForXmlOutput(query);


  12:     }


  13: }








Conversion classes



The following class provides methods for conversion between



1. XML to JSON



2. JSON to XML



3. Object to JSON



4. JSON to Object



5. Dataset to JSON



6. JSON to Dataset



7. XDocument to XmlDocument



8. XmlDocument to XDocument



9. Some dummy conversions to size In MB, time in seconds which might not be of much interest to you all.



For JSON methods, you would require a reference to JSON.NET libraries.





   1: public static class ConversionHelpers


   2:     {


   3:         #region Xml-X Document Conversions


   4:         /// <summary>


   5:         /// Converts XmlNode into an XDocument.


   6:         /// </summary>


   7:         /// <param name="doc">The XMLDocument to be converted</param>


   8:         /// <returns>The XDocument generated</returns>


   9:         public static XDocument AsXDocument(this XmlNode doc)


  10:         {


  11:             return XDocument.Load(new XmlNodeReader(doc));


  12:         }


  13:  


  14:         /// <summary>


  15:         /// converts the XNode into XmlDocument


  16:         /// </summary>


  17:         /// <param name="xdoc">The xdoc.</param>


  18:         /// <returns>the xml document after conversion</returns>


  19:         public static XmlDocument AsXmlDocument(this XNode xdoc)


  20:         {


  21:             var doc = new XmlDocument();


  22:             doc.Load(xdoc.CreateReader());


  23:             return doc;


  24:         }


  25:         #endregion


  26:  


  27:         #region Xml To JSON


  28:         /// <summary>


  29:         /// Converts the XNode passed into JSON String


  30:         /// </summary>


  31:         /// <param name="doc">Xdocument to be converted</param>


  32:         /// <returns>JSON String</returns>


  33:         public static string AsJsonString(this XNode doc)


  34:         {


  35:             return JavaScriptConvert.SerializeXmlNode(doc.AsXmlDocument());


  36:         }


  37:  


  38:         /// <summary>


  39:         /// converts the XML passed into json string.


  40:         /// </summary>


  41:         /// <param name="xml">The XML.</param>


  42:         /// <returns>JSON String notation</returns>


  43:         public static string AsJsonString(this string xml)


  44:         {


  45:             return XDocument.Parse(xml).AsJsonString();


  46:         }


  47:  


  48:         /// <summary>


  49:         /// Opens the XML file mentioned in "fi" and return it as JSON String.


  50:         /// </summary>


  51:         /// <param name="fi"></param>


  52:         /// <returns></returns>


  53:         public static string GetJsonContent(this FileInfo fi)


  54:         {


  55:             if (File.Exists(fi.FullName))


  56:                 return XDocument.Load(fi.FullName).AsJsonString();


  57:             else


  58:             {


  59:                 return null;


  60:             }


  61:         }


  62:  


  63:         #endregion


  64:  


  65:         #region Json to XML


  66:         /// <summary>


  67:         /// Converts the json string into XML


  68:         /// </summary>


  69:         /// <param name="json">JSON as string</param>


  70:         /// <returns>JSON returned as XML</returns>


  71:         public static string AsXml(this string json)


  72:         {


  73:             return JavaScriptConvert.DeserializeXmlNode(json).InnerXml;


  74:         }


  75:         #endregion


  76:  


  77:         #region Object <-> JSON


  78:         public static string ToJSON<T>(this T obj)


  79:         {


  80:             return JavaScriptConvert.SerializeObject(obj);


  81:         }


  82:  


  83:         public static T FromJSON<T>(this string json)


  84:         {


  85:             return JavaScriptConvert.DeserializeObject<T>(json);


  86:         }


  87:         #endregion


  88:  


  89:         #region Dataset <--> JSON


  90:         public static string ToJSON(this DataSet ds)


  91:         {


  92:             return ds.GetXml().AsJsonString();


  93:         }


  94:  


  95:         public static DataSet ToDataset(this string jsonString, bool isXml)


  96:         {


  97:             var ds = new DataSet();


  98:             string asXml = string.Empty;


  99:             if (!isXml)


 100:                 asXml = jsonString.AsXml();


 101:             else


 102:             {


 103:                 asXml = jsonString;


 104:             }


 105:             using (var sr = new StringReader(asXml))


 106:             {


 107:                 ds.ReadXml(sr);


 108:             }


 109:             return ds;


 110:         }


 111:  


 112:         #endregion


 113:  


 114:         #region Others....


 115:         /// <summary>


 116:         /// Computes the size of the byte array in Megabytes


 117:         /// </summary>


 118:         /// <param name="array">byte array to be computed</param>


 119:         /// <returns>size of the array in MB</returns>


 120:         public static double SizeInMB(this byte[] array)


 121:         {


 122:             return array.Length / (1024 * 1024);


 123:         }


 124:  


 125:         /// <summary>


 126:         /// Converst the value into seconds. Basically it divides by 1000.


 127:         /// </summary>


 128:         /// <param name="val">Value in Milliseconds</param>


 129:         /// <returns>Value in seconds</returns>


 130:         public static double TimeInSeconds(this double val)


 131:         {


 132:             return val / (1000);


 133:         }


 134:  


 135:         #endregion


 136:     }




 



Test Data Helpers



In this set of helper classes, I wrote a couple of methods which wrap the most required functionality (at least for me) like generating a random string, getting a random integer, timing an execution. May or may not be useful to you all.





   1: /// <summary>


   2: /// Provides methods for timing execution of an action.


   3: /// Also provides method to generate a byte[] array with all random values.


   4: /// Other Random Helper methods.


   5: /// </summary>


   6: public class TestHelpers


   7: {


   8:     private static Random rand = new Random();


   9:     /// <summary>


  10:     /// This method executes the action passed and then returns the total time


  11:     /// taken in milliseconds using Stopwatch.


  12:     /// </summary>


  13:     /// <param name="action">the action to be performed</param>


  14:     /// <returns>time elapsed in milliseconds</returns>


  15:     public static double TimeAndExecute(Action action, int repeatCount)


  16:     {


  17:         if (repeatCount == 0) return 0;


  18:  


  19:         Stopwatch sw = Stopwatch.StartNew();


  20:         for (int i = 0; i < repeatCount; i++)


  21:             action();


  22:         sw.Stop();


  23:  


  24:         return sw.ElapsedMilliseconds / repeatCount;


  25:     }


  26:  


  27:     /// <summary>


  28:     /// Returns a random byte array of the specified size.


  29:     /// </summary>


  30:     /// <param name="size"></param>


  31:     /// <returns></returns>


  32:     public static byte[] GetBytes(int size)


  33:     {


  34:         var b = new byte[size];


  35:         var rand = new Random(size);


  36:         rand.NextBytes(b);


  37:         return b;


  38:     }


  39:  


  40:     public static int NextIntRand()


  41:     {


  42:         return rand.Next();


  43:     }


  44:  


  45:     /// <summary>


  46:     /// returns a randomly generated string.


  47:     /// </summary>


  48:     /// <param name="length">length of the string to be returned</param>


  49:     /// <returns>string generated</returns>


  50:     public static string GetRandomString(int length)


  51:     {


  52:         return Encoding.Default.GetString(GetBytes(length));


  53:     }


  54: }




 



Simplified Xml querying using Extension Methods.



The following method returns all the elements in the given document (XDocument) with the passed ElementName and which have the specified attribute name and value. I use it a lot for automating my XML documents manipulation.





   1: public static class XDocumentExtensionMethods


   2: {


   3:     public static IEnumerable<XElement> GetDescendantsWithCondition(this XDocument lgxDoc, string ElementName, string AttributeName, string AttributeValue)


   4:     {


   5:         return lgxDoc.Descendants(ElementName).Where(it =>


   6:         {


   7:             XAttribute attribute = it.Attribute(AttributeName);


   8:             return (attribute != null &&


   9:                     attribute.Value == AttributeValue);


  10:         });


  11:     }


  12:  


  13: }




Below are few more helper methods which I use regularly. One of them is the GetCopy() method which returns a copy of the passed XElement.





   1: class XDocumentHelpers{


   2: /// <summary>


   3: /// Modifies the element attribute.


   4: /// </summary>


   5: /// <param name="elementToModify">The element to modify.</param>


   6: /// <param name="attributeName">Name of the attribute.</param>


   7: /// <param name="attributeValue">The attribute value.</param>


   8: public static void ModifyElementAttribute(XElement elementToModify, string attributeName, string attributeValue)


   9: {


  10:     if (elementToModify == null || String.IsNullOrEmpty(attributeName)) Debug.WriteLine("Passed element is NULL");


  11:     else


  12:     {


  13:         XAttribute attribute = elementToModify.Attribute(attributeName);


  14:         if (attribute == null) elementToModify.SetAttributeValue(attributeName,attributeValue);


  15:         else


  16:         {


  17:             attribute.SetValue(attributeValue);


  18:         }


  19:     }


  20: }


  21:  


  22: /// <summary>


  23: /// Adds the element attribute.


  24: /// </summary>


  25: /// <param name="elementToModify">The element to modify.</param>


  26: /// <param name="attribute">The attribute.</param>


  27: /// <param name="attributeValue">The attribute value.</param>


  28: public static void AddElementAttribute(XElement elementToModify, string attribute, string attributeValue)


  29: {


  30:     if (elementToModify == null || String.IsNullOrEmpty(attribute)) Debug.WriteLine("Passed element is NULL");


  31:     else


  32:     {


  33:         if (elementToModify.Attribute(attribute) == null)


  34:         {


  35:             XAttribute xa = new XAttribute(attribute, attributeValue);


  36:             elementToModify.Add(xa); //add the attribute


  37:         }


  38:         else


  39:             ModifyElementAttribute(elementToModify, attribute, attributeValue);


  40:     }


  41: }


  42:  


  43: /// <summary>


  44: /// Deletes the element attribute.


  45: /// </summary>


  46: /// <param name="elementToModify">The element to modify.</param>


  47: /// <param name="attrToDelete">The attr to delete.</param>


  48: public static void DeleteElementAttribute(XElement elementToModify, string attrToDelete)


  49: {


  50:     if (elementToModify == null || String.IsNullOrEmpty(attrToDelete)) Debug.WriteLine("Passed element is NULL");


  51:     else


  52:     {


  53:         XAttribute attribute = elementToModify.Attribute(attrToDelete);


  54:         if (attribute == null) Debug.WriteLine("Could not find the attribute " + attrToDelete);


  55:         else attribute.Remove();


  56:     }


  57: }


  58:  


  59: public static void DeleteNode(XElement element)


  60: {


  61:     if (element == null) return;


  62:     element.Remove();


  63: }


  64:  


  65: public static XElement GetCopy(XElement mainTable)


  66: {


  67:     return XElement.Parse(mainTable.ToString());


  68: }


  69: }



I hope these utility methods provides good information about JSON, XML, XLinq, etc. Let me know if you have any comments to share.