Hugoware

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

Posts Tagged ‘Code

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.

Advertisements

Written by hugoware

August 30, 2010 at 12:19 am

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

Stop, Think, Fix Errors… (Repeat!)

with 2 comments

“Don’t change your code unless you know how it will fix your problem”. If I had to pick a quote to put a ‘squiggly line and my name’ next to, then this would be it.

I’ve seen developers stare blankly at an exception message, comment out a line of code or two and then try and run their code again hoping for the best.

This, of course, rarely fixes anything. Quite often the line of the error message has little to do with the actual problem. Instead, this introduces new errors into your code and causes the problem to take longer to resolve.

Even if you guess and make an exception message go away you still don’t know what caused the error to begin with. Instead, you have a new error that is quietly causing problems and is now much harder to find. They might be ugly, but exception messages are the easiest errors to fix… well, after compiler errors that is…

So, how can you “know” your change will fix the problem? Here are some of the recommendations I make to other developers.

Stop and Think… Carefully

The bug isn’t going anywhere and each time you guess incorrectly you add a new error to your code.

It seems like such a silly thing to even mention, but I’ve seen plenty of developers take a cursory glance at an exception message and then just start changing stuff. It doesn’t even matter if you’re in a “break-fix” situation – you should always carefully consider the problem before changing your code.

Read the error, start following up the stack and think about what could cause this result. Think about the conditions that would cause the error or how you could force the error to happen again.

If you don’t know why your change will fix the code then you aren’t fixing anything.

Understand the Debugger

You don’t need to know what a memory dump is for or how read binary manually to use debugger. Just simply understanding how to set break points and stepping into, over and out of code will probably cover 99% of the problems you encounter.

It might seem daunting at first but don’t ignore the debugger because logging or message boxes are easier to write. Once you get a hang of it, the debugger will most likely become the greatest tool in your future bug squashing adventures.

Isolate and Resolve the Specific Problem

It can be difficult at times to figure out why a section of code doesn’t work when it sits in the middle of a larger application. Sometimes its better to create an empty project and work with a smaller section of the program by itself.

For example, if you don’t understand how a part of your framework is supposed to behave, pull it into a separate program, for example a console application, and work with it until you are comfortable with the results. Then when you integrate your changes back into the main project you can be confident that any remaining errors aren’t part of the newly introduced code.

Look At Open Source Code

If you’ve written some code that is consistently causing problems then consider looking for a framework or open source project instead.

This isn’t a matter of being a good or bad developer. It certainly has nothing to do with being unable to figure out the problem for yourself. Quite simply, code that consistently has errors is probably a difficult problem.

Public frameworks and open source projects are typically owned by other developers that understand the problem better than others. They have taken the time to abstract away the specifics of a problem and build a clean API for other developers to use.

These developers are also typically eager to improve their code and will listen to feedback. Even if you don’t use their project there’s a good chance that you will learn something by simply reading their code.

To sum it up, don’t just change code and hope for the best. Stop, think, ask yourself how does this fix the problem?.

How do you approach fixing problems in your code?

Written by hugoware

June 23, 2010 at 12:02 am

Simple External Templates With jQuery

with 4 comments

New code available: I’ve written a follow up post about this topic with new code and new features.

If you’ve ever tried building a jQuery object from scratch then you’ve probably found that it is a little time consuming and probably a little ugly by the time you’re finished. You could put additional HTML templates as hidden elements on the page but maybe you’d rather keep that extra mark up out of your page.

One option would be load a template from a website address and then make your changes once it arrives. The code would probably look something like this.

//create the container
var element = null;

//make the request for the HTML
$.ajax({
    url:"template.html",
    success:function(html) {
        element = $(html);
        //make changes here
    }
});

There isn’t anything wrong with this code but it does put a bit of separation of your declaration of an element and the actual usage of the element. The problem is that you can’t do the whole process at once since the AJAX call takes a little time and you have to rely on a call back before you have access to the object.

It would be nice if we could have immediate access to our jQuery object on an AJAX call, but not block anything else on the page.

Time For Some Javascript Magic ™

I’m not really sure what you would call the example below, but the general idea is to capture (and queue up) any actions that would be invoked on our jQuery object and then release them once the AJAX call has been finished.

Let’s look at some code and see what it would look like (extra comments to try and explain the process)

/*
 * Arguments
 * $.template(url) - Pass in a string to a url to load 
 * $.template(params) - An object with parameters found below
 *   url: Path to the template resource (required)
 *   data: Same as the 'data' argument in the $.ajax call
 *   error: Same as the 'error' argument in the $.ajax call
 *   complete: Same as the 'complete' argument in the $.ajax call
 *   beforeUpdate: delegate(html) called just before the actual object is created
 *   afterUpdate: delegate(html, actual) called just after the actual object is created
 */

//creates a function to access a web template
jQuery.template = function(params) {
	
	//format the passed in parameters
	//check if this was only the resource url
	if (typeof(params) === "string") {
		params = { url:params };
	}
	
	//prepare the arguments passed into the class
	if (!$.isFunction(params.beforeUpdate)) { params.beforeUpdate = function() {}; }
	if (!$.isFunction(params.afterUpdate)) { params.afterUpdate = function() {}; }
	

	//create the object that handles the work
	var self = {
	
	//Properties
	//---------------------------------------------------------
	
		//handles forwarding methods onto the actual object
		container:null,
		
		//the actual jQuery object being created
		actual:null,
		
		//method calls that are waiting to be called
		queue:[],
		
	//Methods
	//---------------------------------------------------------
		
		//prepares the container for use
		setup:function() {
			
			//apply each of the methods
			self.container = $("<div/>");
			for(var item in self.container) {
				if (!$.isFunction(self.container[item])) { continue; }
				self.register(item);
			}
			
		},
		
		//handles creating method forwarding on the returned object
		register:function(method) {
		
			//create a method that handles routing the original method calls
			self.container[method] = 
				function(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14) {
				
				//if the actual object has been called, just invoke
				if (self.container.actual) {
					return self.container.actual[method](
						p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14
						);
				}
				//otherwise, queue the request
				else {
					self.queue.push({
						action:method,
						params:[p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14]
					});
					
					//then return the temporary object
					return self.container;
				}
			
			};
		
		},
		
		//executes any queued commands and updates the jQuery object
		update:function(html) {
			
			//create the jQuery object
			self.container.actual = $(html);
			
			//then execute all of the waiting commands
			$.each(self.queue, function(i, arg) {
				self.container.actual[arg.action](
					arg.params[0], arg.params[1], arg.params[2], arg.params[3], arg.params[4],
					arg.params[5], arg.params[6], arg.params[7], arg.params[8], arg.params[9],
					arg.params[10], arg.params[11], arg.params[12], arg.params[13], arg.params[14]
					);
			});
		
		},
		
		//starts the ajax request to download the template HTML
		download:function() {
			
			//starts downloading content
			$.ajax({
			
				//parameters for the template request
				url:params.url,
				data:params.data,
				dataType:"html",
				
				//performs the catch up work for the ajax
				success:function(html) {
					//** Optional: Uncomment 'setTimeout' to simulate a delay 
					//setTimeout(function() {
					params.beforeUpdate(html);
					self.update(html);
					params.afterUpdate(html, self.container.actual);
					//}, 2000);
				},
				
				//additional handling of the request
				error:params.error,
				complete:params.complete
			});
		
		},
		
	//Initalization
	//---------------------------------------------------------
		
		//setup the object to work
		init:function() {
		
			//prepare the temporary container
			self.setup();
		
			//start downloading the content
			self.download();
		}
	
	};
	
	//prepare the the template code
	self.init();
	
	//return the custom container to forward method calls
	return self.container;
	
};

This code allows you to have direct access to a jQuery object even before it has finished loading the content from the server. So, instead of using a callback we can write our jQuery like we normally would.

//note: the first command is all one long chain with a comments
//between functions to explain a bit more

//create the object and immediately apply changes
var template = $.template("template.txt")
	.css({"color":"#f00", "width":"200", "background":"#333"})
	.animate({width:800, height:900}, 3000)

	//you can even append and appendTo the object in advance
	.appendTo($("#container"))

	//or search for and update child elements
	.find(".title").text("howdy")

	//and parent elements
	.parent().css({"background":"#00f"});
	
//you can also still access the template from the 
//assigned variable
template.find("div").click(function() {
	alert('clicked');
});

//even if if you call it much later, it still works
setTimeout(function() {
	template.css({"color":"#0f0"});
}, 10000);

What Is Going On Here?

As I mentioned before the real problem is that the jQuery object we create isn’t ready as soon as we want to assign to it. Because of that we have to use a callback to resume the work. However, the cool thing about dynamic languages is that we can override anything we want.

In this example we start by creating a container that has all the same functions as a typical jQuery object but has one slight modification — all the methods are overridden and placed into a queue (man, I love enclosures). Once our AJAX call has completed we run an update command that executes everything we have saved against our new jQuery object instead of the one that received the calls to begin with — madness!

After we’ve caught up and our actual object is created we can stop saving actions to the queue and instead just invoke them immediately. I nicknamed this method forwarding for the sake of having a cool, buzzword sounding sort of name but if anyone knows what this is really called, please tell me 🙂

It is worth noting that this is only going to work with functions that return the jQuery object (at least until the ‘real’ object is created). The reason is that since we’re just capturing methods and saving them for later then we don’t know what the actual return type is. Needless to say, using a property probably won’t be accurate either (since we can’t intercept the request for the property like we would with a method)

In any case, this might simplify the next time you need to download content in jQuery but you don’t want to break up your functionality.

Written by hugoware

January 14, 2010 at 10:59 pm

Undo, Redo and Whatever… From A Web Application

with 2 comments

Long ago a brilliant developer invented the Undo command — probably one of the most important features to be added in computing history. It seems funny to me that today, in 2009, it is still a very rare feature to find on a website. This isn’t to say no one is doing it but more that it isn’t a common feature to find.

Using Lambdas For Undo Actions

In .NET you can use Lambdas to create a function and pass it around like an argument and then that argument can then be invoked at a later time in a different place. That said, with a little careful planning and a few correctly stored Lambdas, you could have a working ‘Undo’ model in your ASP.NET web sites For this example I’m going to use MVC but this would really work anywhere.

Warning: This is very crude code, more of a proof of concept, so you probably don’t want to use it in your projects as is.

Let’s start with an abstract controller that contains our Undo handling code.

[UndoController.cs]

using System;
using System.Web;
using System.Web.Mvc;

namespace UndoAction {

	//class that supports an undo action
	public class UndoController : Controller {

		#region Constants

		private const string SESSION_UNDO_ACTION = "Session:UndoAction";
		private const string SESSION_UNDO_MESSAGE = "Session:UndoMessage";
		private const string TEMP_DATA_UNDO_MESSAGE = "UndoResult";
		private const string DEFAULT_UNDO_MESSAGE = "Previous action was undone!";
		private const string DEFAULT_MISSING_UNDO_MESSAGE = "No actions to undo!";

		#endregion

		#region Undo Action Container (Session)

		//contains the current undo action
		private static Action _UndoAction {
			get {
				return System.Web.HttpContext.Current
					.Session[SESSION_UNDO_ACTION] as Action ;
			}
			set {
				System.Web.HttpContext.Current
					.Session[SESSION_UNDO_ACTION] = value;
			}
		}

		//the message to return in the view data for this action
		private static string _UndoMessage {
			get {
				return System.Web.HttpContext.Current
					.Session[SESSION_UNDO_MESSAGE] as string ;
			}
			set {
				System.Web.HttpContext.Current
					.Session[SESSION_UNDO_MESSAGE] = value;
			}
		}

		#endregion

		#region Setting Undo Actions

		/// <summary>
		/// Applies an undo action
		/// </summary>
		protected void SetUndo(Action action) {
			this.SetUndo(DEFAULT_UNDO_MESSAGE, action);
		}

		/// <summary>
		/// Applies an undo action with a return message for the user
		/// </summary>
		protected void SetUndo(string message, Action action) {
			UndoController._UndoAction = action;
			UndoController._UndoMessage = message;
		}

		/// <summary>
		/// Performs the undo action (if any) and saves the message
		/// </summary>
		protected void PerformUndo() {

			//check if there is an action
			if (UndoController._UndoAction is Action) {

				//perform the action and save the message
				Action action = UndoController._UndoAction;
				action();
				this.TempData[TEMP_DATA_UNDO_MESSAGE] =
					UndoController._UndoMessage;

				//and clear out the previous information
				UndoController._UndoAction = null;
				UndoController._UndoMessage = null;

			}
			//just save a generic message
			else {
				this.TempData[TEMP_DATA_UNDO_MESSAGE] =
					DEFAULT_MISSING_UNDO_MESSAGE;
			}

		}

		#endregion

	}

}

Basically, we create an abstract Controller that allows us to set an Undo action using a Lambda. You can also set a message for to return to the user that sumarizes what the action had done. This example uses a couple Session variables to hold the parts of the undo action, except I recommend that you create an actual class to house all of the information.

Next, let’s look at how we would actually use this controller.

[HomeController.cs]

using System;
using System.Collections.Generic;
using System.Web.Mvc;
using System.Linq;

namespace UndoAction {

	//example of using undo actions
	public class HomeController : UndoController {

		#region Constants

		private const string SESSION_LIST_CONTAINER = "Session:ListContainer";

		#endregion

		#region Properties

		//a simple list of items for the list
		public static List<string> ListContainer {
			get {
				List<string> container = System.Web.HttpContext.Current.Session[SESSION_LIST_CONTAINER] as List<string>;
				if (container == null) {
					container = new List<string>();
					System.Web.HttpContext.Current.Session[SESSION_LIST_CONTAINER] = container;
				}
				return container;
			}
		}

		#endregion

		#region Actions

		//shows the list of items
		public ActionResult Index() {
			return this.View(HomeController.ListContainer.OrderBy(item =&gt; item.ToLower()));
		}

		//adds an item to the list
		public ActionResult Add(string phrase) {

			//format the value
			phrase = (phrase ?? string.Empty).Trim();

			//add the item if it isn't there yet
			if (!HomeController.ListContainer.Any(item => item.Equals(phrase, StringComparison.OrdinalIgnoreCase)) &amp;&amp;
			    !string.IsNullOrEmpty(phrase)) {
				HomeController.ListContainer.Add(phrase);
			}

			//return to the list view
			return this.RedirectToAction("Index");

		}

		//removes an item from the list
		public ActionResult Delete(string phrase) {

			//make sure the item even exists first
			if (HomeController.ListContainer.Any(item => item.Equals(phrase, StringComparison.OrdinalIgnoreCase))) {

				//since it exists, save the logging message
				this.SetUndo(
					string.Format("Restored '{0}' to the list!", phrase),
					() => {
						HomeController.ListContainer.Add(phrase);
					});

				//and then actually remove it
				HomeController.ListContainer.Remove(phrase);

			}

			//return to the main page
			return this.RedirectToAction("Index");

		}

		//tries to undo the previous action
		public ActionResult Undo() {

			//attempts to undo the previous action (if any)
			this.PerformUndo();

			//return to the main page
			return this.RedirectToAction("Index");
		}

		#endregion

	}

}

This controller allows the user to manage a simple shopping list with an Undo action to allow them to restore a deleted item. It is some ugly code, but you get the idea on how it works.

The important thing you should note is that the Lambda doesn’t refer to the instance of the class (this) but instead that the list is a static property. This is important to keep in mind as you develop something like this. When you create the Lambda action, you can’t refer to the instance that it was created in. Instead, you need to work with static properties.

Finally, let’s look at the ViewPage that is used in this example.

[Index.aspx]

<%@ Page Language="C#" 
	Inherits="System.Web.Mvc.ViewPage" %>
<%@ Import Namespace="System.Collections.Generic" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<title>Shopping List</title>
	</head>
	<body>
		<% IEnumerable<string> list = this.Model as IEnumerable<string>; %>
		
		<h2>Shopping List</h2>
		
		<p><% =this.Html.ActionLink("Undo Previous Action", "Undo") %></p>
		
		<% if (this.TempData["UndoResult"] is string) { %>
		<p><em><% =this.TempData["UndoResult"] as string %></em></p>
		<% } %>
		
		<hr />
		
		<table>
		<% foreach(string item in list) { %>
			<tr>
				<td><% =this.Html.Encode(item) %></td>
				<td><% =this.Html.ActionLink("Remove", "Delete", new { phrase = item }) %></td>
			</tr>
		<% } %>
		</table>
		
		<hr />
		
		<form action="<% =this.Url.Action("Add") %>" method="post" >
			<strong>Add an item:</strong>
			<input type="text" name="phrase" />
			<input type="submit" value="Add" />
		</form>
		
	</body>
</html>

The ViewPage itself is nothing fancy — If you’re working in a project you should create a strongly-typed view but in this example we just read the information we need and go on.

Using The Page

Below are a few screen shots of what happens as the user makes changes to the page. This example starts with a list of a few different items.

After removing an item from the list (the ‘Orange’) pressing the ‘Undo Previous Action’ button will restore the item. The custom message that was added is displayed (from the TempData field).

If you press the ‘Undo’ button again there aren’t any actions waiting anymore and the default message is displayed instead (no actions waiting).

Things To Consider

This code is just a sample of how you could implement and Undo function into your web applications. Here are a few things that you might want to keep in mind before starting something like this.

  • Make sure that your Undo command doesn’t cause you to duplicate code. In this example, the undo command uses a different ‘Add’ approach than the actual ‘Add’ action on the controller. This could result in duplicated code or incorrect results.
  • Determine if you can queue up ‘Undo’ commands. This example can only do one action at a time, but you could potentially create a Stack of actions that are executed in the reverse order that they were added.
  • Could you use the same concept to ‘Redo’ a command after it has been undone?
  • Be careful with your context – Don’t use ‘this’ inside of your Undo Lambdas.

Anyways, just an interesting concept to share. This approach requires a lot more thought but could pay off in the end.

Do you have a web application that could benefit from an ‘Undo’ command?

Written by hugoware

December 21, 2009 at 12:03 am

Enums, Flags and C# — Oh my! (bad pun…)

with 12 comments

New Code! An updated blog post on this topic can be found here!

I’m not sure about everyone else, but I just love Enumerated types. Whats more, I love the Flags Attribute when you combine them together. This post explores how you can use these two things along with Extension Methods to make your code more compact and easier to understand.

If you’ve never used this combination before, then you’re missing out. Consider the following code…

class User {
    bool CanDelete;
    bool CanRead;
    bool CanWrite;
    bool CanModify;
    bool CanCreate;
}

Okay, so that’s no big deal even though it may be quite a few extra lines of code. It would be nice to be able to combine all of those permissions into a single value. That’s where an Enumerated Type with a FlagAttribute comes in.

[Flags]
enum PermissionTypes : int {
    None = 0,
    Read = 1,
    Write = 2,
    Modify = 4,
    Delete = 8
    Create = 16,
    All = Read | Write | Modify | Delete | Create
}

//and the class from before
class User {
    PermissionTypes Permissions = PermissionTypes.None;
}

Excellent…. so now what?

So now whats great about this is now we can assign multiple values onto the same property. Not only that, but we can also check for existing values with a (strange) comparison.

//create a new user
User admin = new User();
admin.Permissions = PermissionTypes.Read 
    | PermissionTypes.Write 
    | PermissionTypes.Delete;

//check for permissions
bool canRead = ((PermissionTypes.Read & admin.Permissions) == PermissionTypes.Read);
bool canWrite = ((PermissionTypes.Write & admin.Permissions) == PermissionTypes.Write);
bool canCreate = ((PermissionTypes.Create & admin.Permissions) == PermissionTypes.Create);

//and the results
Console.WriteLine(canRead); //true
Console.WriteLine(canWrite); //true
Console.WriteLine(canCreate); //false

Now shorter and easier to read — sorta. See that really odd comparison? That’s what you need to write each time you want to check for a value. It’s not that bad, but it isn’t really something I’d like to type very often. You could write a separate function to do these comparisons for you, but we can do even better than that.

Taking Advantage Of Extension Methods

Since an Enumerated type isn’t really a class you can’t extend methods onto them. However, you can extend methods onto the class System.Enum. Methods added to this class will appear in the methods for all of your enumerated types!.

Here is an example method…

//full class included at the end of the post
public static class EnumerationExtensions {

        //checks to see if an enumerated value contains a type
        public static bool Has<T>(this System.Enum type, T value) {
            try {
                return (((int)(object)type & (int)(object)value) == (int)(object)value);
            } 
            catch {
                return false;
            }
        }
}

Now, this code does make an assumption that it can cast your Enumerated Type to an integer. You could do some type checking before you do the comparisons, but for the sake of this example, we’re going to keep this short.

So just how do you use this extension?

//start with a value
PermissionTypes permissions = PermissionTypes.Read | PermissionTypes.Write;

//then check for the values
bool canRead = permissions.Has(PermissionTypes.Read); //true
bool canWrite = permissions.Has(PermissionTypes.Write); //true
bool canDelete = permissions.Has(PermissionTypes.Delete); //false

Now that is much easier to read! Even better, you’ll notice despite the fact this has a Generic parameter, we don’t have to provide the type at the start since the method can infer it from the parameter (implicitly typed parameters — sweeeeet!)

And don’t forget, System.Enum isn’t the only class you can do this with, there are other classes (like System.Array for example) that you can add your own extension methods to for surprising results!

Below is the full source code for the EnumerationExtensions class. If you have any improvements, please let me know!

namespace Enum.Extensions {

    public static class EnumerationExtensions {

        //checks if the value contains the provided type
        public static bool Has<T>(this System.Enum type, T value) {
            try {
                return (((int)(object)type & (int)(object)value) == (int)(object)value);
            } 
            catch {
                return false;
            }
        }

        //checks if the value is only the provided type
        public static bool Is<T>(this System.Enum type, T value) {
            try {
                return (int)(object)type == (int)(object)value;
            }
            catch {
                return false;
            }    
        }

        //appends a value
        public static T Add<T>(this System.Enum type, T value) {
            try {
                return (T)(object)(((int)(object)type | (int)(object)value));
            }
            catch(Exception ex) {
                throw new ArgumentException(
                    string.Format(
                        "Could not append value from enumerated type '{0}'.",
                        typeof(T).Name
                        ), ex);
            }    
        }

        //completely removes the value
        public static T Remove<T>(this System.Enum type, T value) {
            try {
                return (T)(object)(((int)(object)type & ~(int)(object)value));
            }
            catch (Exception ex) {
                throw new ArgumentException(
                    string.Format(
                        "Could not remove value from enumerated type '{0}'.",
                        typeof(T).Name
                        ), ex);
            }  
        }

    }
}

Written by hugoware

June 13, 2009 at 2:59 am