Hugoware

The product of a web developer with a little too much caffeine

Archive for August 2010

Anonymous Types As Object Templates

with 6 comments

I’ve got a bit of an addiction to intellisense. Dynamic types are interesting but I still prefer being able to see a nice neat list of properties on each of my objects.

Since anonymous types are ‘real’ classes then you can actually create them at runtime. This means you can use them as templates for other objects if you can provide all of the required parameters.

Below is a simple class that allows you to perform queries against a database and use an anonymous type to provide a template for the records to return.

/// <summary>
/// Helps working with database connections
/// </summary>
public class DataConnection {

    #region Constructors

    /// <summary>
    /// Creates a new DataConnection for the connection string
    /// </summary>
    public DataConnection(string connection) {
        this.ConnectionString = connection;
    }

    #endregion

    #region Properties

    /// <summary>
    /// The connection string to use with this DataConnection
    /// </summary>
    public string ConnectionString { get; private set; }

    #endregion

    #region Performing Queries

    /// <summary>
    /// Performs a query for the connection without any parameters
    /// </summary>
    public IEnumerable<T> Query<T>(string query, T template)
        where T : class {
        return this.Query(query, (object)null, template);
    }

    /// <summary>
    /// Performs a query for the connection with the provided paramters
    /// </summary>
    public IEnumerable<T> Query<U, T>(string query, U parameters, T template)
        where T : class 
        where U : class {

        //prepare the connection and command
        Type type = template.GetType();

        //create the connection - (thanks @johnsheehan about the 'using' tip)
        using (SqlConnection connection = new SqlConnection(this.ConnectionString)) {
            using (SqlCommand command = new SqlCommand(query, connection)) {

                //assign each of the properties
                if (parameters != null) {
                    this._UsingProperties(
                        parameters,
                        (name, value) => command.Parameters.AddWithValue(name, value));
                }

                //execute the query
                connection.Open();
                SqlDataReader reader = command.ExecuteReader();

                //start reading each of the records
                List<T> results = new List<T>();
                Dictionary<string, int> fields = null;
                while (reader.Read()) {

                    //prepare the fields for the first time if needed
                    fields = fields == null ? this._ExtractFields(reader) : fields;

                    //generate the record
                    T record = this._CreateAnonymousResult(reader, fields, type, template);
                    results.Add(record);
                }

                //return the results for the query
                return results.AsEnumerable();
            }

        }

    }

    #endregion

    #region Helpers

    //creates a new anonymous type from 
    private T _CreateAnonymousResult<T>(SqlDataReader reader, Dictionary<string, int> fields, Type templateType, T template)
        where T : class {

        //create a container to queue up each record
        List<object> values = new List<object>();

        //use the template to find values
        this._UsingProperties(template, (name, @default) => {

            //try and find the field name
            if (fields.ContainsKey(name)) {

                //check if this is a value
                int index = fields[name];
                object value = reader[index];
                Type convert = @default.GetType();

                //try and copy the va;ue
                if (value != null) {
                    values.Add(Convert.ChangeType(value, convert));
                }
                //not the same type, use the default
                else {
                    value.Equals(@default);
                }

            }
            //no field was found, just use the default
            else {
                values.Add(@default);
            }

        });

        //with each of the values, invoke the anonymous constructor
        //which accepts each of the values on the template
        try {
            return Activator.CreateInstance(templateType, values.ToArray()) as T;
        }
        catch (Exception e) {
            Console.WriteLine(e.Message);
            return template;
        }

    }

    //reads a set of records to determine the field names and positions
    private Dictionary<string, int> _ExtractFields(SqlDataReader reader) {
        Dictionary<string, int> fields = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
        for (int i = 0; i < reader.FieldCount; i++) {
            fields.Add(reader.GetName(i), i);
        }
        return fields;
    }

    //performs an action with each of the properties on an object
    private void _UsingProperties(object obj, Action<string, object> with) {
        
        //if there isn't anything to work with, just cancel
        if (obj == null) { return; }

        //get the type and peform an action for each property
        Type type = obj.GetType();
        foreach (PropertyInfo prop in type.GetProperties()) {
            with(prop.Name, prop.GetValue(obj, null));
        }

    }

    #endregion

}

This class allows us to perform basic queries against a database and then provide a template of the records to return. This means that if the information is found then the database value is used but if it is missing then the template value is used instead.

In order to create an anonymous type we need to know the type and each of the properties in the order they appear. After collecting this information we simply need to use the Activator.CreateInstance method to instantiate the class and we’re set! (method _CreateAnonymousResult)

This means we can write a ‘dynamic’ query with results that have intellisense!

//set up the connection
DataConnection data = new DataConnection(CONNECTION_DATA);

//perform the query
var results = data.Query(
    "select * from orders where orderId > @orderId",
    new { orderId = 11000 },
    new {
        orderId = -1,
        shipName = "missing",
        shipRegion = "none"
    });

//access properties
var record = results.First();
int id = record.orderId; //intellisense!

I’ve actually used this same approach before in CSMongo as a way to provide intellisense without knowing anything about the database in advance.

Of course, this is just some code I hacked out this evening. You aren’t going to be able to do a lot with it but it is a good example of how you can reuse anonymous types in your code.

Written by hugoware

August 30, 2010 at 12:19 am

Using jLinq With JSON APIs

leave a comment »

I’ve had a few e-mails asking how to perform a query on JSON data from an external source, for example Flickr Services. This post we will go over accessing Flickr data but also performing a secondary query on the information returned.

You can download a .zip file at the end of the post with the files used in the examples.

Let’s take a look at what we’re going to create…

You can see we’ve included a search box along with a few additional check boxes with options we can use for the secondary query. These options aren’t available for the API call, but we can intercept the records and apply additional filters before we use them on the page.

To start, we need to create an extension method for downloading the data from the Flickr APIs. jLinq allows you to create extension methods and plug them directly into the framework.

//extend jLinq to search Flickr
jlinq.flickr = function(search, action) {
    search = escape(search);
    $.getJSON(
        "http"+"://api.flickr.com/services/feeds/photos_public.gne?"+
        "tagmode=any&format=json&jsoncallback=?&tags="+search, 
        function(data) {
            var query = jlinq.from(data.items);
            action(query);
        });
};

This example creates a method named flickr that resides with the rest of the jLinq library. The method accepts a keyword to search with and an anonymous function that will be used to work with the data. This is because we have to wait for the server to return a response.

This means you would use the function with a search phrase and a jLinq query to perform.

//start a new jLinq query
jlinq.flickr("cake", function(query) {

    //perform a normal query and use the data
    query.contains("title", "red")
        .sort("title");
});

At this point we need to wire up all of the UI elements on the page. I won’t go into detail on this part but you can always refer to the example for help if you get stuck.

So lets take a step back and take a look at how the filtering is done for the records. You’ll notice that we can selectively perform certain parts of the query depending on which check boxes are selected.

//sample.js - line 31     - - - - - -
//if excluding titles with digits
if (flickr.ui.filterNumbers.is(":checked")) {
    query.notMatch("title", /\d/g);
}

//if requiring a photo to have a title
if (flickr.ui.requireTitle.is(":checked")) { 
    query.notEmpty("title"); 
}

//if requiring sorting of titles
if (flickr.ui.sortTitle.is(":checked")) { 
    query.sort("title"); 
}

//snip...

You’ll notice that you don’t have to chain the entire query together. You can do sections at a time. This means you can decide when certain parts of the script run and when they are skipped.

Now, we can write queries against Flickr and also perform our own secondary queries using jLinq. In this case we are sorting data and filtering out records that wasn’t part of the query to the server.

Of course, this is a simple example but is does show some of the neat ways you can you can use jLinq to help you work with JSON data.

[Sample Files]
http://hugoware.com/examples/jlinq-flickr.zip

Written by hugoware

August 26, 2010 at 1:12 am

Null Instance Extension Methods

with 4 comments

Checking for null can be time consuming and add a lot of extra noise to the code you write. In some ways it can reduce the readability of your code and obscure the purpose of your functions.

For example, check out all of the null checks required for this bit of code.

public static int GetVersion() {
	
	//check if this exists
	if (!File.Exists(PATH_APP_DETAILS)) { return DEFAULT_VERSION; }

	//try and load the document
	XDocument document = null;
	try {
		document = XDocument.Load(PATH_APP_DETAILS);
	}
	catch {
		return DEFAULT_VERSION;
	}
	if (document == null) { return DEFAULT_VERSION; }
	
	//find the element
	XElement release = document.XPathSelectElement("app/release");
	if (release == null) { return DEFAULT_VERSION; }
	
	//get the value
	XAttribute version = release.Attribute("version");
	if (version == null) { return DEFAULT_VERSION; }
	
	//convert the version
	int current = int.TryParse(version.Value, out current) ? current : DEFAULT_VERSION;
	return current;
	
}

Yikes… that is a lot of code for such a small task but what else can you do? You can’t just call methods on something that is null or your app is going to blow up… or can you?

Null Instance Extension Methods

Extension methods feel magical the first time you see them in action but ultimately they are just static methods that can be invoked from anywhere in your project.

But here is the neat thing — Since an extension method isn’t tied to the instance of a class then they can be invoked without an instance of the class.

Sound confusing? Here is an example of what I mean…

//create an extension method
public static class StringExtensions {
	public static void Test(this string value) {
		Console.WriteLine("Hello from a null test!");
	}
}

//and then call it
string nothing = null;
nothing.Test(); //ok!
nothing.ToUpper(); //crash

You’ll notice that the call to Test worked fine – If you put a break point in the method and check the value argument then you’ll notice it is actually null! We were able to call the method Test even though there wasn’t an instance of a string.

So how can this help us? Well let’s take the same XML problem from earlier in the post and create some extension methods that don’t care if the instance being invoked is null or not.

//helper extension methods for XML documents
public static class XmlExtensions {
	
	//loads an xml document to use
	public static XDocument LoadDocument(this XDocument document, string path) {
		if (!File.Exists(path)) { return null; }
		try { return XDocument.Load(path); }
		catch { return null; }
	}
	
	//uses an XPath to find an element
	public static XElement GetElement(this XDocument document, string path) {
		return document is XDocument ? document.XPathSelectElement(path) : null;
	}
	
	//returns the value of an attribute
	public static string GetAttribute(this XElement element, string name) {
		XAttribute attribute = element is XElement ? element.Attribute(name) : null;
		return attribute is XAttribute ? attribute.Value : string.Empty;
	}
}

Now let’s take a look at how we can solve the same problem as before but with these new extension methods…

public static int GetVersion() {
	
	//open the document (Mono)
	XDocument document = document.LoadDocument(PATH_APP_DETAILS);

	//It appears you have to do it like this in Visual Studio
	//XDocument document = ((XDocument)null).LoadDocument(PATH_APP_DETAILS);
	
	//find the element
	XElement release = document.GetElement("app/release");
	
	//get the version
	string version = release.GetAttribute("version");
	
	//convert and return the value
	int current = int.TryParse(version, out current) ? current : DEFAULT_VERSION;
	return current;
}

As far as I can tell, no matter what you throw at this code, you will either get the default version or the value in the XML document. This definitely reduces the lines of code count… but the clarity gains might be debatable.

  1. A developer modifying this code might not realize the value could be null or could be a real object. If they call an instance method and the value ends up being null then the application is going to crash.
  2. Some developers are going to scratch their heads when they read the line XDocument document = document.LoadDocument(...). Invoking a method on a value you’re declaring and should be null and returning the result it to itself? Huh?
  3. The more forgiving your code is then the more prone to external errors it will be, which in turn will introduce subtle runtime errors in your applications. Sometimes it’s a better idea just to throw an exception and keep the program from running.

So, while this approach has benefits it also has pitfalls. Make sure to evaluate the risks before using something like this in your code. If implemented carefully this could reduce complexity in your application…

…or at least make for a neat parlor trick the next time you’re with your dev team.

Written by hugoware

August 22, 2010 at 9:14 pm

Installing CobaltMVC

with one comment

Got an interesting piece of anonymous feedback today reminding me of something rather obvious…

How exactly do you install CobaltMVC?

Oh yeah… That would be handy information… and it probably should have already been released. That said, lets get right to it.

Download CobaltMVC

The new CobaltMVC site is still in beta (like the rest of the framework) but you can still download the libraries you need to get started.

Add CobaltMVC To Your Project

Unpack the files to an easy to reach location and then add them as references to your project. You don’t need to add both, the Cobalt.dll is good enough.

‘Initialize’ CobaltMVC

Next, open up the Global.asax file and include the Cobalt.CobaltConfiguration.Initialize(); call to the Application_Start method. This makes sure that CobaltMVC is set up fully before it begins processing requests.

Update Web.config (sorta optional)

This step can be skipped but it will make coding your pages less convenient since you’ll have to add the namespaces all over the rest of your project. Add the Cobalt and the Cobalt.Web namespaces to your system.web/pages/namespaces section. This opens up the extension methods used to start Cobalt commands from your views.

You’re Done!

At this point we can test CobaltMVC to see if it is working. For example, here is a command you can run on the default MVC Index view.

And you’ll get the following results…

Not bad, huh?

It is worth mentioning that CobaltMVC might have unexpected results if you use .browser files with your project. Why?

Well, part of the Initialize() call actually creates a .browser file that is used to capture rendering for content on the page.

So, if you see this file floating around in your project, don’t delete it.

Who knows what happens when too many .browser files are fighting for the same thing but I doubt it will be a good thing.

Good luck!

Written by hugoware

August 20, 2010 at 12:09 am

3 Things To Know Before Using jLinq

leave a comment »

Since I released the beta code for the new jLinq I’ve had several of the same questions show up. Here are some answers to help you get started.

Where Is ‘Manual’, Query Commands Are ‘Auto-pilot’

I’ve had a few questions where people start trying to use the where command and find that it isn’t solving anything.

As far as I can tell, a lot of other LINQ style Javascript libraries use Where as their query command and have the developer manually provide the comparisons. Granted, I don’t know the other frameworks very well (hint, I wrote my own) but a lot of the code samples look something like this.

var results = lib.From(data)
    .Where(function(record) { return record.name.substr(0, 1) == "a"; })
    .OrderBy(function(record) { return record.name; })
    .Select();

I’m sure that these libraries are doing a lot of stuff for you in the background, but the where command in itself seems like placing too much work on the developer.

jLinq approaches this differently. Instead, you’ll find many common query methods included as part of the library. These methods also evaluate the data types to determine the best way to query the property.

Here is an example, consider you have some data that looks like this.

var data = [{
    name: "James",
    permissions: ["read", "write", "delete"]
},
/* snip... */];

Instead of checking these records manually, you can use the same command for both properties and they will handle the data differently for each.

//with string types
jlinq.from(data).contains("name", "e").select(); //matches the 4th 'e' in 'James'

//with array types
jlinq.from(data).contains("permissions", "write").select(); //matches the 2nd 'write'

This reduces the typing you do since you no longer have to perform manual comparisons.

Of course, jLinq does include a where command that uses the same syntax as the example above (anonymous function), but it is recommended to create extension methods instead of using the where command.

Operators Are Query Commands Too

Operators are an important part of jLinq. Sometimes you’d like to match on more than one condition or ignore records that do not meet a certain condition. You can use operators as individual commands in your queries.

//Examples only - Shorter syntax explained in Section 3

jlinq.from(data)
    .starts("first", "a")
    .or()
    .starts("first", "b");

jlinq.from(data)
    .not()
    .starts("first", "d")

jLinq takes operators a step further by creating operator aliases for all of the query commands in your library. This means that instead of only having the query command starts you actually have 6 – starts, orStarts, andStarts, notStarts, orNotStarts, andNotStarts. The queries above can be rewritten as.

//Examples only - Shorter syntax explained in Section 3

jlinq.from(data)
    .starts("first", "a")
    .orStarts("first", "b")
    .select()

jlinq.from(data)
    .notStarts("first", "d");

It is worth noting that and is the implied default unless you provide an or – the and versions of the query commands are for aethestetics only. 🙂

DRY — I Repeat, DRY!

If you aren’t familiar with the term DRY, it means “Don’t Repeat Yourself”. The previous samples reduced some of our typing, but jLinq can actually take it a step further.

jLinq uses field and command memorizing, meaning after you say it once it is implied until you say something different.

jlinq.from(data)
    .starts("first", "a")
    .or("b")
    .or("c");

jlinq.from(data)
    .starts("first", "a")
    .ends("b")
    .or("last", "a");

The first example memorizes the command being used is starts and the field being queried is first. After that, the remaining calls to ‘or’ will repeat the previous command and field unless something else is used.

The second example shows how you can mix up commands and field names without needing to repeat yourself. Basically, here is what the query is doing.

  1. Records with first names starting with ‘a’…
  2. then records with first names ending with ‘b’…
  3. then records with last names ending with ‘a’

You can see that jLinq makes it easy to avoid repeating the same commands and field names to reduce the typing.

This is just some of the first basics to understand about jLinq. I’ll be blogging more (and writing documentation) for the next few days. Feel free to contact me with questions.

Written by hugoware

August 11, 2010 at 9:54 pm

jLinq Reloaded

with 5 comments

[jLinq Beta is now online – go check it out!]

My first ‘open source’ project I ever released was a Javascript library that allowed you perform LINQ style queries with arrays of objects. The library supported operators, extension methods and even memorized commands to reduce typing.

Overall, it did a good job of making it easier to select information that normally would need to be handled with a for loop. Unfortunately, it turns out jLinq is rather slow. I recently blogged about a performance evaluation that came back with less than flattering results.

However, this is exactly where ‘open source’ helps make better software. If I hadn’t released my code then I might never know how it could be improved. This is the sort of thing that inspires software developers to improve their code — and that is exactly what is did for me.

So for the past few days I’ve been completely rewriting jLinq from the ground up and the gains have been incredible to say the least.

  1. About 60% smaller (around 8kb compressed)
  2. 99% faster queries
  3. Easier to extend library
  4. Minty fresh scent (your results may vary)

If you’re looking for a download link then you’re going to have to contact me instead. The code should be released soon but for now I’m still writing tests and preparing to rerelease the project with a brand new site (and probably a new name).

[http://github.com/hugoware/jlinq-beta/]

There has been a lot of interest already in seeing the new code so I’ve started a new repository on github.com. This is beta code so I suspect I’ll have errors in it. Please feel free to contact me to log an issue on the site.

If you’re interested in how jLinq improved so much then read on…

jLinq… But On Caffeine

My first theory about why jLinq was so slow had to do with the use of evals in my code.

At the time, I didn’t understand you could pass functions as arguments, I certainly had no idea what enclosures were, so jLinq would build an entire query in a string and then eval it into a method that could be invoked against each record.

I also used eval to get values from records instead of just referring to them by their names as an index. I don’t know why eval is so much slower, but the difference is undeniable.

//using index names
var fast = function(obj, path) {
    path = (path+"").split(/\./g);
    var index = 0;
    while(obj != null && index < path.length) {
        obj = obj[path[index++]];
    }
    return obj;
};

//being lazy with an eval
var slow = function(obj, path) {
    return eval("obj."+path);
};

//looping 100,000 times
loop(100000, function() { fast(data, "name.first"); }); //128ms
loop(100000, function() { slow(data, "name.first"); }); //6.8 minutes

So what kind of improvement do these two changes result in? Big ones.

Single Argument Query (850 Records)
Previously: ~430ms
Now: ~10ms

Multi-Argument Query with Strings (850 Records)
Previously: ~2730ms
Now: ~35ms

Simple Join (850 Records)
Previously: ~6200ms
Now: ~135ms

The list of improvements goes on but I’ll talk about them more in later blog posts.

So What Is Next?

It’s screaming fast and much smaller but unfortunately it is too new to even suggest that it is put into production. I’ll definitely feel more confident in the code after I’ve finished the tests.

But I also plan to rebrand the library this time. Why?

As it turns out, the name LINQ has caused some confusion with non-.NET developers. I’ve heard that some developers see the name and say ‘Well, I don’t use .NET so I don’t need this.’, which is clearly not the response I’d like to hear.

jLinq isn’t only for web pages. In fact, the neat thing about jLinq is that it can be plugged into anything running Javascript and it works great. I’d like to see jLinq be exposed to more developers.

So, with a new name, new site and all brand new code I think there is a chance to redefine what jLinq can do for the community.

The code is mostly finished so now it’s time for the hard part… coming up with a good name…

Written by hugoware

August 8, 2010 at 8:53 pm

More Control When Parsing Values

with 4 comments

As much as you might try, sooner or later you’re going to wind up parsing string values and converting them into their correct type. It is… inevitable.

If you’re going for clarity then this only takes a couple lines of code to accomplish. For example…

int value = default(int);
int.TryParse("44", out value);

No big deal, in fact it is possible to do on a single line of code…

int value = int.TryParse("44", out value) ? value : default(int);

Of course, this line of code is going to draw more questions from some of the less experienced developers on your team, but hey… doesn’t it just scream ‘Alpha Programmer’?

Parsing integers isn’t really a big deal in itself but wouldn’t it be nice if the entire process could be done on one line with one method and allow you to supply default values… and without causing confusion?

Below is an example of how you might create a class that handles parsing for you.

/// <summary>
/// Handles parsing string values to appropriate types
/// </summary>
public static class Parse {

	#region Static Constructor

	//prepares the Parse class
	static Parse() {
		Parse._CustomParsing = new Dictionary<Type, Func<string, object>>();
	}

	#endregion

	#region Properties

	//holds custom parse methods
	private static Dictionary<Type, Func<string, object>> _CustomParsing;

	#endregion

	#region Public Methods

	/// <summary>
	/// Registers a custom parsing method
	/// </summary>
	public static void RegisterType<T>(Func<string, object> compare) {
		Type type = typeof(T);
		Parse._CustomParsing.Remove(type);
		Parse._CustomParsing.Add(type, compare);
	}

	/// <summary>
	/// Attempts to parse a value and return the result
	/// but falls back to the default value if the conversion fails
	/// </summary>
	public static T TryParse<T>(string value) {
		return Parse.TryParse(value, default(T));
	}

	/// <summary>
	/// Attempts to parse a value and falls back to the
	/// provided default value if the conversion fails
	/// </summary>
	public static T TryParse<T>(string value, T @default) {
		value = (value ?? string.Empty).ToString();
		Type type = typeof(T);

		//so much can go wrong here, just default to the
		//fall back type if the conversions go bad
		try {

			//perform custom parsing first
			if (Parse._PerformCustomParse(type, value, ref @default)) return @default;

			//check if this is a nullable and if we should use a child type
			//this might not work with VB since the nullable name could be different
			if (type.IsGenericType && type.Name.StartsWith("Nullable`")) {
				
				//underlying type for a nullable appears to be the first argument
				type = type.GetGenericArguments().FirstOrDefault();
				
				//if no type was found then five up
				if (type == null) { return @default; }

				//try custom parsing with the underlying type if this was a nullable
				if (Parse._PerformCustomParse(type, value, ref @default)) return @default;
			}

			//try the remaining parsing methods
			if (type.IsEnum && Parse._PerformEnumParse(type, value, ref @default)) return @default;
			if (Parse._PerformParse(type, value, ref @default)) return @default;

			//finally, just try a conversion
			Parse._PerformConvert(type, value, ref @default);
			return @default;

		}
		//settle for the default
		catch {
			return @default;
		}

        }

	#endregion

	#region Checking Values

	//uses custom parsing methods
	private static bool _PerformCustomParse<T>(Type with, string value, ref T result) {

		//if there is no custom type, cancel
		if (!Parse._CustomParsing.ContainsKey(with)) { return false; }

		//find the conversion
		Func<string, object> parse = Parse._CustomParsing[with];

		//attempt to parse
		try {
			object converted = parse(value);
			bool success = converted is T;
			if (success) { result = (T)converted; }
			return success;
		}
		//if the attempt failed
		catch {
			return false;
		}

	}

	//tries to parse using an Enum
	private static bool _PerformEnumParse<T>(Type with, string value, ref T result) {

		//check for a result
		try {
			object parsed = Enum.Parse(with, value, true);
			bool success = parsed is T;
			if (success) { result = (T)parsed; }
			return success;
		}
		catch {
			return false;
		}

	}

	//searches for a 'Parse' method
	private static bool _PerformParse<T>(Type with, string value, ref T result) {

		//make sure a try parse was even found
		MethodInfo method = with.GetMethods().FirstOrDefault(item =>
			item.Name.Equals("parse", StringComparison.OrdinalIgnoreCase) &&
			item.IsStatic);
		if (method == null) { return false; }

		//check for a result
		try {
			object parsed = method.Invoke(null, new object[] { value, result });
			bool success = parsed is T;
			if (success) { result = (T)parsed; }
			return success;
		}
		catch {
			return false;
		}

	}

	//performs common conversions
	private static bool _PerformConvert<T>(Type type, string value, ref T result) {
		object convert = Convert.ChangeType(value, type);
		bool success = convert is T;

		//update the type if needed
		if (success) { result = (T)convert; }
		return success;
	}

	#endregion

}

The general idea behind this code is to attempt to parse using a variety of ways and then fall back to a default value if nothing works out. This way we can get in and out of parsing values without needing to split up the code.

There is an ugly little bit of reflection in there, so if your application can’t incur that kind of penalty hit you might want to fall back to the classic parsing methods.

int count = Parse.TryParse("44", 0); // 44
bool success = Parse.TryParse("cheesecake", true); // true
decimal = Parse.TryParse("3.01", 3M); // 3.01

Additionally, this code allows you to add your own parsing methods to the class and use the same method across the entire project.

//register our own parsing method
Parse.RegisterType<Color>(value => ColorTranslator.FromHtml(value));
Parse.RegisterType<decimal>(value => {
    value = Regex.Replace(value, @"[^0-9\.]", string.Empty);
    return decimal.Parse(value);
    });

//use it just like any other value
Color color = Parse.TryParse("#ff0000", Color.Blue);
decimal total = Parse.TryParse("$45.33", 0M);

You could take the extension methods a step further by adding the same functionality to your strings. For example.

/// <summary>
/// Extensions to quickly parse string types
/// </summary>
public static class StringExtensions {

	/// <summary>
	/// Parses a string to the correct type or default value
	/// </summary>
	public static T ToType<T>(this string value) {
		return value.ToType(default(T));
	}

	/// <summary>
	/// Parses a string to the correct type or default value
	/// </summary>
	public static T ToType<T>(this string value, T @default) {
		return Parse.TryParse(value, @default);
	}
	
}

This would allow you to perform the conversions from the string itself and avoid the call to a static method floating around in the project.

bool admin = "true".ToType<bool>();
int count = "3334".ToType<int>();
Color blue = "something".ToType(Color.Blue);
Color green = "#00ff00".ToType(Color.Red);

Parsing values isn’t hard but is certainly doesn’t hurt to make it a bit easier.

Written by hugoware

August 5, 2010 at 1:29 am

jLinq Performance Analyzed

with 2 comments

After writing this post I went back and rewrote jLinq from the ground up to improve performance.

So here is something interesting. Another developer named Dan Stocker has been working on a Javascript sorting library named jOrder and used jLinq for comparing benchmarks. The results are interesting to say the least.

Dan has a good write up of the results in the wiki for his project.

I’m disappointed, but in a good way. I thought jLinq was ‘good enough’. It performed the way it should and that was good enough for me. These results tell a much different story.

jLinq probably performs well in typical scenarios, whereas these benchmarks are for medium to large arrays queried thousands of times. I’ve used it in several projects with great results.

Regardless, jLinq clearly performs slower than it should. Reviewing the jLinq code I can think of a few potential pain points.

  1. The entire jLinq object and all of the commands are generated each time a query is started. jLinq there should be a way to cache a standard jLinq object and only rebuild it when needed.
  2. jLinq uses a lot of evals that probably could have been avoided if I understood Javascript better at the time. This undoubtedly is going to cause a significant performance hit.

jLinq was written just about a year and a half ago and I’ve since learned some of the finer parts of Javascript which would most likely improve the performance of the library. In fact, seeing this review has really inspired me to get into back into the project and see what kind of improvements I can make.

I appreciate Dan showing these results to me. Sharing your code with others is a great way to get feedback about what you write… even if it is a kick in the butt.

Written by hugoware

August 4, 2010 at 8:43 am