Pivoting POCO generic lists using reflection

by martin 7. November 2011 22:05
I recently had to pivot data that I had in a list of POCO objects.  I had to do this for a couple of different object types and it just felt wrong to have to recode something so generic over and over again.  So... I figured I'd write a little helper class that utilizes reflection and allows me to pivot on any list of POCO objects, and specify what I want to pivot on (X and Y columns) and what I should be summing.  This is all done using System.Collections.Generic and System.Reflection so it may not be the ideal solution from a performance perspective for huge datasets.  On the other hand, for most datasets and modern hardware it isn't a problem at all, and it is really flexible and very highly reuseable for cranking out reports quickly.
 
Code Snippet
  1. public class PivotResult
  2. {
  3.  
  4.     public String[] ColumnNames;
  5.     public String[] RowNames;
  6.     public float[,] ValuesTable;
  7.     public int Count;
  8. }
  9. public class ReflectionPivot
  10. {
  11.     public PivotResult Pivot(List<Object> ObjectList, String ColumnProperty, String RowProperty, String ValueProperty)
  12.     {
  13.         if (ObjectList == null)
  14.             return null;
  15.         if (ObjectList.Count == 0)
  16.             return null;
  17.         Object first = ObjectList[0];
  18.         Type type = first.GetType();
  19.         PropertyInfo[] properties = type.GetProperties();
  20.         PropertyInfo colPropInfo = null;
  21.         PropertyInfo rowPropInfo = null;
  22.         PropertyInfo valPropInfo = null;
  23.         foreach (PropertyInfo pInfo in properties)
  24.         {
  25.             if (pInfo.Name.Equals(ColumnProperty))
  26.                 colPropInfo = pInfo;
  27.             if (pInfo.Name.Equals(RowProperty))
  28.                 rowPropInfo = pInfo;
  29.             if (pInfo.Name.Equals(ValueProperty))
  30.                 valPropInfo = pInfo;
  31.         }
  32.         if (colPropInfo == null)
  33.         {
  34.             throw new ArgumentException("Column Property invalid.");
  35.         }
  36.         if (rowPropInfo == null)
  37.         {
  38.             throw new ArgumentException("Row Property invalid.");
  39.         }
  40.         if (valPropInfo == null)
  41.         {
  42.             if (!(ValueProperty.Equals("1")))
  43.             {
  44.                 throw new ArgumentException("Value Property invalid.");
  45.             }
  46.         }
  47.         List<String> lstColNames = new List<string>();
  48.         List<String> lstRowNames = new List<string>();
  49.         foreach (Object obj in ObjectList)
  50.         {
  51.             string strCol = colPropInfo.GetValue(obj, null).ToString();
  52.             string strRow = rowPropInfo.GetValue(obj, null).ToString();
  53.             if (!(lstColNames.Contains(strCol)))
  54.             {
  55.                 lstColNames.Add(strCol);
  56.             }
  57.             if (!(lstRowNames.Contains(strRow)))
  58.             {
  59.                 lstRowNames.Add(strRow);
  60.             }
  61.         }
  62.         PivotResult pr = new PivotResult();
  63.         pr.Count = 0;
  64.         pr.ValuesTable = new float[lstRowNames.Count, lstColNames.Count];
  65.         pr.RowNames = lstRowNames.ToArray();
  66.         pr.ColumnNames = lstColNames.ToArray();
  67.         foreach (Object obj in ObjectList)
  68.         {
  69.             float fVal = 0;
  70.             if (ValueProperty.Equals("1"))
  71.             {
  72.                 fVal = 1;
  73.             }
  74.             else
  75.             {
  76.                 fVal = (float)valPropInfo.GetValue(obj, null);
  77.             }
  78.             pr.Count++;
  79.             string strCol = colPropInfo.GetValue(obj, null).ToString();
  80.             string strRow = rowPropInfo.GetValue(obj, null).ToString();
  81.             int intColName = lstColNames.FindIndex(x => x == strCol);
  82.             int intRowName = lstRowNames.FindIndex(x => x == strRow);
  83.             pr.ValuesTable[intRowName, intColName] += fVal;
  84.         }
  85.         return pr;
  86.     }
  87. }
 
 
And you would use it something like this: 
 
ReflectionPivot reflectionPivot = new ReflectionPivot();
PivotResult pivotResult = reflectionPivot.Pivot(intermediate.ToList<Object>(), "Team", "Grade", "1"); 
PivotResult pivotResult2 = reflectionPivot.Pivot(lstSales"Division""State""Sales"); 
 
And then you can simply pass the PivotResult instance to a MVC view and use it to display a graph or to just show in a table list like this:
 
Code Snippet
  1. <%@ Page Title="Sales Report" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<PivotResult>" %>

  2. <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
  3.  
  4.     <script src="<%: Url.Content("~/Scripts/visualize.jQuery.js") %>" type="text/javascript"></script>
  5.     <script type="text/javascript">
  6. //<![CDATA[
  7.             $(function () {
  8.                 $(".jqvisualizesimple").visualize();
  9.             });
  10.         });
  11. //]]>
  12.     </script>
  13.  
  14. <h2>Sales Report</h2>
  15.  
  16. <table class="jqvisualizesimple">
  17. <thead>
  18. <td>&nbsp;</td>
  19. <% foreach(var strCol in Model.ColumnNames) { %>
  20. <th scope="col"><%: strCol %></th>
  21. <% } %>
  22. </thead>
  23. <tbody>
  24.     <% for (int i = 0; i < Model.ValuesTable.GetLength(0); i++)
  25.        {
  26.            var strRow =  Model.RowNames[i]; %>
  27.            <tr><th scope="row"><%: strRow %></th>
  28.        <%
  29.            for (int j = 0; j < Model.ValuesTable.GetLength(1); j++)
  30.            { %>
  31.        <td><%:Model.ValuesTable[i, j]%></td>
  32.     <%     }
  33.        }%>
  34. </tr>
  35. </tbody>
  36. </table>
  37. </asp:Content>
  
 
I was really hoping to do this using pure LINQ, but it turned out to be the much more difficult route so I ended up backing off and using reflection instead.  If someone has seen something like this done in LINQ, please do send me a message or a comment and point towards that solution as I would very much enjoy seeing it and learning from it. 

Currently rated 1.5 by 1075 people

  • Currently 1.489765/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

C#

Writing Extended ASCII codes with BinaryWriter in .Net

by martin 12. October 2011 16:10
Ok, so this seems simple enough, but it took me a bit of Googling to figure out that I needed to pass the magic number 1252 to the GetEncoding method to get this to work correctly.  ASCIIEncoding only encodes values from 0 to 127 correctly, but values 128 to 255 do not get written out properly.  1252 refers to the Window Code Page for the Latin Alphabet for Western languages, and is sometimes incorrectly referred to as ANSI.  Hopefully this will save someone else some time searching for the solution.....
 
Code Snippet
  1. String strEscapeCode = new String('\xC4', 5);
  2.  
  3. using (FileStream stream = new FileStream("TestFile.bin", FileMode.Create))
  4. {              
  5.     using (BinaryWriter writer = new BinaryWriter(stream, Encoding.GetEncoding(1252)))
  6.     {
  7.         writer.Write(strEscapeCode.ToCharArray());
  8.         writer.Close();
  9.     }
  10. }

Currently rated 2.7 by 6 people

  • Currently 2.666667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

C#

Using Secure Hashing safely in .Net

by martin 5. October 2011 22:41

SHA 1 and SHA 256 are both great hashing algorithms, but both are susceptible to a Rainbow Table attack and with Moore's law and the great race by Google, Bing, and other search engines to index absolutely every bit of data out there on the internet, the chances of these attack succeeding grows every day.  As a developer fending off this kind of vector, it is considered a best practice to not only always salt your data before hashing it, but to always make sure that the salt is completely random in nature.  Additionally, since both SHA 1 and SHA 256 are Big - O(n) algorithms as far as performance cost is concerned and relatively inexpensive to execute on modern hardware, it is also a good idea to have multiple iterative calls to the hashing algorithm to come up with the hash.  And while we are at it, we might as well switch up between using both algorithms just in case one has a yet undiscovered flaw similar to that which was discovered with MD-5 or even SHA-0 before that.  Below is a C# implementation of a secure hash helper class to help you do all this.  It provides a way to create a hash from a value and to confirm that a hash was made from a given value.  It currently does additional Base64 encoding/decoding of the hash value for ease of use in web applications (tamper proofing forms against request forgery, storing password hashes, etc), but this can easily be removed if you'd prefer to deal in raw byte arrays.

 
Code Snippet
  1. using System;
  2. using System.Security.Cryptography;
  3.  
  4. namespace SecureHashTestConsole
  5. {
  6.     public static class SecureHashHelper
  7.     {
  8.         // set this to a relatively small number that you like.  (4 to 25 suggested range)  Larger number = longer random hash
  9.         private const int defaultNumBytesForSeed = 9;
  10.  
  11.         // set this to a decent number, not too low, not to high (5 to 1000 suggested range)  Larger number = slower performance but less likely rainbow table cracking possibility
  12.         private const int defaultIterations = 88;     
  13.  
  14.         public static bool CompareSecureHash(string TestHash, string TestValue, int numRandBytesForSeed = defaultNumBytesForSeed, int iterations = defaultIterations)
  15.         {
  16.             byte[] hashArray = Convert.FromBase64String(TestHash);
  17.             byte[] derivedSalt = new byte[numRandBytesForSeed];
  18.             Buffer.BlockCopy(hashArray, 0, derivedSalt, 0, numRandBytesForSeed);
  19.             string strComp = CreateSecureHash(TestValue, derivedSalt, iterations);
  20.             return strComp.Equals(TestHash);
  21.         }
  22.  
  23.         public static string CreateSecureHash(byte[] sbuffer, int numRandBytesForSeed = defaultNumBytesForSeed, int iterations = defaultIterations)
  24.         {
  25.             RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
  26.             byte[] randSalt = new byte[numRandBytesForSeed];
  27.             rand.GetBytes(randSalt);
  28.             return CreateSecureHash(randSalt, sbuffer, iterations);
  29.         }
  30.  
  31.         public static string CreateSecureHash(string ValueToHash, int numRandBytesForSeed = defaultNumBytesForSeed, int iterations = defaultIterations)
  32.         {
  33.             RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
  34.             byte[] randSalt = new byte[numRandBytesForSeed];
  35.             rand.GetBytes(randSalt);
  36.             System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
  37.             Byte[] bytes = encoding.GetBytes(ValueToHash);
  38.             return CreateSecureHash(randSalt, bytes, iterations);
  39.         }
  40.  
  41.         private static string CreateSecureHash(string ValueToHash, byte[] randSalt, int iterations = defaultIterations)
  42.         {
  43.             System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
  44.             Byte[] bytes = encoding.GetBytes(ValueToHash);
  45.             return CreateSecureHash(randSalt, bytes, iterations);
  46.         }
  47.         private static string CreateSecureHash(byte[] randSalt, byte[] sbuffer, int iterations = defaultIterations)
  48.         {
  49.             SHA1Managed sha1 = new SHA1Managed();
  50.             SHA256Managed sha256 = new SHA256Managed();
  51.  
  52.             byte[] buffer = new byte[randSalt.Length + sbuffer.Length];
  53.             Buffer.BlockCopy(randSalt, 0, buffer, 0, randSalt.Length);
  54.             Buffer.BlockCopy(sbuffer, 0, buffer, randSalt.Length, sbuffer.Length);
  55.  
  56.             for (int i = 0; i < iterations; i++)
  57.             {
  58.                 // flip the order of using these two around if you want longer hashes
  59.                 sha256.ComputeHash(buffer);
  60.                 buffer = sha256.Hash;
  61.                 sha1.ComputeHash(buffer);
  62.                 buffer = sha1.Hash;
  63.             }
  64.  
  65.             byte[] output = new byte[buffer.Length + randSalt.Length];
  66.             Buffer.BlockCopy(randSalt, 0, output, 0, randSalt.Length);
  67.             Buffer.BlockCopy(buffer, 0, output, randSalt.Length, buffer.Length);
  68.  
  69.             return Convert.ToBase64String(output);
  70.         }
  71.     }
  72. }

Here is a simple console driver application that demonstrates its usage:

Code Snippet
  1. using System;
  2.  
  3. namespace SecureHashTestConsole
  4. {
  5.     class Program
  6.     {
  7.         static void Main(string[] args)
  8.         {
  9.             var testValues = new[] {"Testing" , "2", "4343", "help", "This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here"};
  10.             foreach (string strTestValue in testValues)
  11.             {
  12.                 for (int i = 0; i < 10; i++)
  13.                 {
  14.                     String hash = SecureHashHelper.CreateSecureHash(strTestValue);
  15.                     Console.WriteLine("Hash #{0} of '{1}' = '{2}'", i+1, strTestValue, hash);
  16.                     Console.WriteLine("Comparison = {0} (should be True)", SecureHashHelper.CompareSecureHash(hash, strTestValue));
  17.                     Console.WriteLine("Comparison = {0} (should be False)", SecureHashHelper.CompareSecureHash(hash, strTestValue + " "));
  18.                 }
  19.             }
  20.         }
  21.     }
  22. }

Example Output

Hash #1 of 'Testing' = 'qxj1uwwjKs+4sP9mUc96gpUIVYRcyD2FliNh'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #2 of 'Testing' = '4E7baUemZRmM7oYWk2aWdQ5jpnQ8OJcr4HmS'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #3 of 'Testing' = '0RRhLyFefkcLP9X5qWp/Nih8RNjezPzHm2hM'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #4 of 'Testing' = '/c2cdFCuc+eWAOxp192gSeSdNzWkddxkOuvD'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #5 of 'Testing' = 'OWrWE/821zy8siYjnGA+VD6UYXFRJjaW9gom'

Comparison = True (should be True)

Comparison = False (should be False)

 

.....................................

 

 

Hash #10 of 'help' = 'yiTptJocrqyFRpp6Hlk4/cXF04T6SQdsqqt7'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #1 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'qeIzv06CJeDXzu4p3K/uFSxcqVH45Wm6ESjo'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #2 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'xrQm1kuNrczVrdONoS8sRjddq0zq2si02hyN'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #3 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'WO7aN2lXoZgg7m0EYDnKqoRQw7mg3CSH0ori'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #4 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'CgQq75ZBm40P2IrNzaVZRBBCjjn3QdlN2Ivt'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #5 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'wXGXvdU1TBQCluwL2Kce1x4SbUU0YuFup31V'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #6 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'Xzpdr5p4RHJ1O24LdDxruL4+nw+NOp0tjrsh'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #7 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'kYFQgmaZp3VG1LjwYslKdGHZg7nnlZfLHDHB'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #8 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'nA/7Ky7xbMpAZ1OVuLF7Ku/0YarzZXpKIfA8'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #9 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'b875hD3alHDPv4yrl46GsvgGtuQOLpsECj7o'

Comparison = True (should be True)

Comparison = False (should be False)

Hash #10 of 'This is a test to see if the hash will be small even though the text is a bit bigger than the others that are listed here' = 'BJHwf4plv/t0Hpx1oi0l0VuZa9Dq0FppYI2J'

Comparison = True (should be True)

Comparison = False (should be False)

Currently rated 1.6 by 83 people

  • Currently 1.554216/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

ASP.Net | C#

Utility for Encrypting .Net App.Config Sections

by martin 18. July 2011 23:00

.Net ships with aspnet_regiis.exe for encrypting configuration sections in Web.Config files, but there seems to be no quick and dirty way to do this in non-web applications.  Sure, if you are packaging up software into an installation package, you can add your own custom installation action to encrypt a configuration section (see The Code Project : Implementing Protected Configuration With Windows Apps).  Or you can write code into your application to automatically encrypt a config section if it encounters it in an unencrypted state (see The Code Project : Encrypting the app.config File for Windows Forms Applications).  If you have IIS installed on the box, you can even rename your App.config to web.config and still use aspnet_regiis (see DotNetProfessional.com: Encrypt Sections of Web.config or App.config).  But what if you just want a quick way to encrypt a config section or two without all the fuss?  Or, better yet, what if you forget a password or some other important secret that is already encrypted in an app.config somewhere and you need to get it back.

 

Here is a simple little command line app that allows you to do app.config section encryption and decryption without having to write any addtional code (The .Net framework already takes care of decrypting these values automatically for us when we use them in our code).  Only this one small EXE is required and the standard MS .Net 2.0+ runtime dlls that are already installed on your system.

AppConfigSectionEncyptor.exe (7 kb)

Below are the "Usage" instructions that result from running the EXE without any parameters.  "-e" is for encrypt, "-u" is for unencrypt.

C:\>AppConfigSectionEncyptor.exe
Usage:  AppConfigSectionEncyptor.exe [-e|-u] [-d] file section

Examples:

        AppConfigSectionEncyptor -e c:\MyCode\MyApp.exe mySecureSection
        AppConfigSectionEncyptor -e -d c:\MyCode\MyApp.exe mySecureSection
        AppConfigSectionEncyptor -u c:\MyCode\MyApp.exe mySecureSection
Please note that 'file' is the path to the EXE, not the config file itself.
Please note that you need adaquate permissions to the keystore for this to work.

-d = use the DPAPIProtectedConfigurationProvider for encryption instead of the default RSAProtectedConfigurationProvider.

 

I hope that you find this useful, but as always, here is the disclaimer:

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 

Currently rated 1.7 by 56 people

  • Currently 1.696426/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , ,

C# | Windows

Sorting custom data objects the easy way

by martin 28. September 2009 22:32

I recently had to implement custom sorting on couple of ASP.net pages that had to bind to a collection of custom data objects.  Not wanting to re-invent the wheel on every page, I looked for an easier solution online.  I ran across at least two worth mentioning: Generic Sorting Using Reflection in .NET By Jon Wojtowicz (http://www.eggheadcafe.com/articles/pfc/propertycomparer.asp) and Rocky Lhotka's MSDN article where he presents his Generics based PropertyComparer.  I liked Jon's solution in that it was written using recursion so that you could easily sort by properties of properties.  However Jon's implementation was not "Generics" based.  Rocky's implementation was generics based, but it lacked the recursion that my solution needed.  In the end, I ended up modifying Jon's code to be generics based.  I sent Jon an email asking for permission to share his modified code online, but unfortunately he never responded to my email.

Below is a link to my patch file to Jon's PropertyComparer.cs file.  You can download the original directly from Jon's project hosted on EggHeadCafe in the link above.

PropertyComparer.patch (2.99 kb)

Here is an example of how you would use this to support sorting in a Telerik RadGrid:

        protected void RadGrid1_SortCommand(object source, GridSortCommandEventArgs e)
        {
            List<Employee> employees = (List<Employee>)RadGrid1.DataSource;
            CompareOrder cmpOrder;
            GridSortExpression expression = new GridSortExpression(); 

            if (e.NewSortOrder.Equals(GridSortOrder.Ascending))
            {
                cmpOrder = CompareOrder.Ascending;
                expression.SortOrder = GridSortOrder.Ascending;
            }
            else
            {
                cmpOrder = CompareOrder.Descending;
                expression.SortOrder = GridSortOrder.Descending;
            }

            employees.Sort(new PropertyComparer<Employee>(e.SortExpression, cmpOrder));

            expression.FieldName = e.SortExpression;

            e.Item.OwnerTableView.SortExpressions.Clear();
            e.Item.OwnerTableView.SortExpressions.AddSortExpression(expression);
            e.Item.OwnerTableView.Rebind();
            e.Canceled = true;
        } 
 

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , , ,

ASP.Net | C#

RegEx helper method to make extracting patterns from strings a cinch

by martin 12. July 2009 15:10

Quite often I find myself trying to create a custom string from the “pattern” found in an input string.  Through trial and error, I have found a real simple and powerful way to do this, and here it is!  It works simply by using the grouping operator “()” for regular expressions and utilizing the power of String.Format.  This implementation is written as a .Net 3.5 extension method for the String class.  I overloaded it to be more flexible; you can pass in RegexOptions, a String representation of a regular expression, or a precompiled Regex object for optimal efficiency.  One important note is that Regex works such that the entire expression is always the first group match (grouping 0) and that all groupings that you explicitly state start at grouping number 1 and enumerate up from there.

StringRegexHelper.cs (1.54 kb)

    1 using System;

    2 using System.Text.RegularExpressions;

    3 

    4 namespace CustomExtensions

    5 {

    6     public static class StringRegexHelper

    7     {

    8         public static String FindAndFormat(this String StringToSearch,

    9             Regex RegularExpressionToSearchFor, String FormattingExpression)

   10         {

   11             String strResult = null;

   12             Match match = RegularExpressionToSearchFor.Match(StringToSearch);

   13             if (match.Success)

   14             {

   15                 String[] arrCaptures = new String[match.Groups.Count];

   16                 for (int i = 0; i < match.Groups.Count; i++)

   17                 {

   18                     arrCaptures[i] = match.Groups[i].Captures[0].Value;

   19                 }

   20                 strResult = String.Format(FormattingExpression, arrCaptures);

   21             }

   22             return strResult;

   23         }

   24 

   25         public static String FindAndFormat(this String StringToSearch,

   26             String RegularExpressionToSearchFor, String FormattingExpression)

   27         {

   28             return FindAndFormat(StringToSearch,

   29                 new Regex(RegularExpressionToSearchFor),

   30                 FormattingExpression);

   31         }

   32 

   33         public static String FindAndFormat(this String StringToSearch,

   34             String RegularExpressionToSearchFor, String FormattingExpression,

   35             RegexOptions RegularExpressionOptions)

   36         {

   37             return FindAndFormat(StringToSearch,

   38                 new Regex(RegularExpressionToSearchFor,

   39                     RegularExpressionOptions),

   40                 FormattingExpression);

   41         }

   42     }

   43 }

Here are 3 examples of how this can be used:

    1 strResult = "myusername-file1.txt".FindAndFormat(@"(\w+)-.",

    2     "{1}@ad.domain.com");

    3 // Returns "myusername@ad.domain.com"

    4 

    5 strResult = "BatchFile072009.txt".FindAndFormat(@"BatchFile(\d\d)(\d\d\d\d)\.txt",

    6     "Batch file for year {2} and month {1} retrieved from {0}");

    7 // Returns "Batch file for year 2009 and month 07 retrieved from BatchFile072009.txt"

    8 

    9 String strInput = "John_Doe;123-45-6789;04/12/2005";

   10 strResult = strInput.FindAndFormat(@"(\w+)_(\w+);(\d{3})-(\d{2})-(\d{4});(\d+)/(\d+)/(\d+)",

   11     "Last name = {2}  First name = {1}  SSN = {3}{4}{5}  DOB = {6}-{7}-{8}");

   12 // Returns "Last name = Doe  First name = John  SSN = 123456789  DOB = 04-12-2005"

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

C#

Welcome

Please contact me if you have a great idea for a project and need technical expertise in designing, developing, or integrating a custom software solution.

Recent Comments

Comment RSS