Click here to Skip to main content
15,886,724 members
Articles / Programming Languages / C#
Article

DataParser Helper Class

Rate me:
Please Sign up or sign in to vote.
1.29/5 (4 votes)
14 Apr 20074 min read 20.5K   106   9   1
Helper/Utility class to easily convert and/or provide defaults in variable conversions.

Introduction

Many times in your DotNet coding, you will need to convert or test a variable to determine whether it is of some "type" (e.g.: is myVar an integer?) And sometimes if your variable in question is null or not the type you are expecting, you might want to default to some predefined value (e.g.: is myVar an integer, no? Then assign -1.) This article addresses that functionality via a helper class called DataParser.

Without a helper class, we might see code like the following:

C#
int myDefaultValue = -1;        // defaultValue
object inputData = myVarToTest; // my inputted value supplied from some 
                                // untrustworthy source as a string
int def = myDefaultValue;
int myEndResult = myDefaultValue;

try
{
    if (null == inputData) return def;
    // side note about the TryParse below, please don't flame me
    // about what is the best way to test and convert to a numeric.
    // for those interested, google the idea, there's lots of religious 
    // debate out there.
    if (Int32.TryParse(inputData.ToString(), out result))
    {
        return result;
    }
    else
    {
        return def;
    }
}
catch
{
    return def;
}

Or we might see the try/catch used as the only determination of defaulting. Using the try/catch may not be the best option due to performance issues. But I'll leave that debate up to the performance gurus.

C#
int myDefaultValue = -1;
string myVarToTest = "twenty";      // my inputted value supplied from some
                                    // untrustworthy source as a string
int myEndResult = myDefaultValue;   // default

try
{
    myEndResult = Convert.ToInt32(myVarToTest);
}
catch
{
    myEndResult = myDefaultValue;
}

return myEndResult;

Generally I dislike writing the same code blocks twice. Worse, in the case of testing request parameters on each aspx page, I might have written those blocks for multiple web pages in my app, multiplied per request parameter passed to each page. For example, the variables "userId", "categoryId", "subcategoryId", "sessionId" passed across 10 pages, could equate to 40 code blocks if not more. Blah! Code duplication and boring work.

Of course, my example is purely to communicate the basic issue, and, yes, there are a million ways to skin that cat with refactoring, etc.

So I have developed a DataParser "helper", which helps in type conversions and defaults when needed, encapsulating the logic surrounding these functions.

In a future article, I will demonstrate how to wrap the DataParser helper in a request parameter type parser class to locate and handle those pesky request parameters (aspx) and convert them with ease.

Using the code

The DataParser (for the most part) assumes that a variable being passed is a DotNet Object. From the Object type, the code will start determining whether our "object" is of the type you are interested in returning.

C#
public static class DataParser
{
    public static string GetStringParameter(object inputData)
    {
        return Convert.ToString(inputData);  
            //this will error if there is a failure
    }

    //this method provides a fall-back (default) in case of failure

    public static string GetStringParameter(object inputData, string def)
    {
        try
        {
            if(null == inputData)
            {
                return def;
            }

            if((string)inputData == string.Empty)
            {
                return def;
            }

            // feel free to add whatever else you want to check for here.
            return GetStringParameter(inputData);    
            // and, finally, let's try to convert
            // this variable (object) to a string.
        }
        catch
        {
            // if we made it here, something bad happened, 
            // so toss in the towel and send back the default.
            return def;
        }
    }
}

    ... and so on (download the code for a full example)

The GetStringParameter(object <code>inputData, string def) excepts the "object" you want to convert to a string and a default (def) string value to use in the case where your object turns out to not be what you want (e.g. NULL or String.Empty).

I created two signatures, one with a default option and the other without. The signature without a default option will error if a problem occurs. This is useful if you need to control the ability to test for failure or throw the Exception within your code.

Note: the way in which the code is "determining" and "defaulting" is not necessarily the main point here – I am presenting one of many approaches. The core concept is to encapsulate "how" you think this should be done, put it in a library, use the library, and reduce code duplication (i.e. write it once and reuse it often.)

So at this point, I could call the code such as the following (NUnit) test.

C#
[Test]
public void ParseString1_woDefault_wString()
{
    string input1 = "string";
    string output1 = DataParser.GetStringParameter(input1);
    Assert.AreEqual(output1, input1);
}

Or an example where we send NULL to the method.

[Test]
public void ParseString1_Default_wNull()
{
    string input1 = null;
    string output2 = "default";
    string output1 = DataParser.GetStringParameter(input1, output2);
    Assert.AreEqual(output1, output2);
}

Now let's take a quick look at handling integers.

C#
public static int GetIntParameter(object inputData)
{
    return Convert.ToInt32(inputData);     // errors if not an integer
}

public static int GetIntParameter(object inputData, int def)
{
    int result = -1;

    try
    {
        if(null == inputData) return def;

        if(Int32.TryParse(inputData.ToString(), out result))
        {
            return result;
        }
        else
        {
            return def;
        }
    }
    catch
    {
        return def;
    }
}

These methods basically follow the same logic as the GetStringParameter() method except that we try to determine whether our inputData is an integer.

Again, the innards of the method (how I am determining what is an Integer) is not as important as the concept of the helper class/method. However, in this case let me emphasize that the TryParse(myValue) technique is much faster than using a try/catch block. Google "TryParse" and "Performance" to read through some of the published metrics (or religious wars) on these two approaches. In my case, the moment I read about the TryParser(), I updated my library and my code did run faster (e.g., unscientific test showed a huge increase when working with a large record set from how I had previously written the code.) This demonstrates my point, that by using the library class I was able to update and "better" my code across multiple pages and applications by simply editing the innards of the GetIntParameter() method.

So at this point, we can easily test for our integer with the following line of code.

C#
int output1 = DataParser.GetIntParameter(someUntrustedValue, -1);

That's one line of code versus our original example of ~13 lines of code. To go a step further, here's our original example, referring to the four parameters passed into an aspx page.

C#
int myDefault = 1;
int myUserId = DataParser.GetIntParameter(userId, myDefault)
int myCategoryId = DataParser.GetIntParameter(categoryId, myDefault);
int mySubCategoryId = DataParser.GetIntParameter(subcategoryId, myDefault);
int mySessionId = DataParser.GetIntParameter(sessionId myDefault);

MyProcess(myUserId, myCategoryId, mySubCategoryId, mySessionId);
//process the variables as you please...

That's 7 lines of code versus a possibility of 52+ lines of code (if you didn't wise-up and write a private function in your page.) And better yet, if you find that one of your methods has an error or could be improved (e.g., performance-wise), you only have one place to change the code - which I have experienced as stated above.

Obviously this is not a new concept. But it is worth repeating and reinforcing in our teams. The amount of time you take to write the helper library will pay you back many times in the future. Of course, how to organize and decide to write and share helper libraries is another issue altogether.

The source code included with this article has the following methods.

C#
string GetStringParameter(object inputData);
string GetStringParameter(object inputData, string def);

int GetIntParameter(object inputData);
int GetIntParameter(object inputData, int def);

double GetDoubleParameter(object inputData);
double GetDoubleParameter(object inputData, double def);

float GetFloatParameter(object inputData);
float GetFloatParameter(object inputData, float def);

long GetLongParameter(object inputData);
long GetLongParameter(object inputData, long def);

short GetShortParameter(object inputData);
short GetShortParameter(object inputData, short def);

bool GetBooleanParameter(object inputData);
bool GetBooleanParameter(object inputData, bool def);

char GetCharParameter(string name);
char GetCharParameter(string name, char def);

DateTime GetDateTimeParameter(object inputData);
DateTime GetDateTimeParameter(object inputData, DateTime def);

Guid GetGuidParameter(string guid);
Guid GetGuidParameter(object guid);
Guid GetGuidParameter(object guid, string def);
Guid GetGuidParameter(object guid, Guid def);
Guid GetGuidParameter(string guid, Guid def);

byte GetByteParameter(string name);
byte GetByteParameter(string name, byte def);

bool IsNumeric(string inputData);

History

  • DataParser was originally inspired by my conversion of Java code written by Jason Hunter (the port was done years ago, and the original source is unknown.)
  • Version 2.0 of the DataParser (presented here) converted the helper to DotNet 2.0 and to a static class.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 1 Pin
Mizan Rahman10-Jul-12 3:48
Mizan Rahman10-Jul-12 3:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.