Hugoware

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

Posts Tagged ‘C#

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

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

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

Cobalt Progress

with 2 comments

CobaltMVC is coming along really well. I’ve been dog fooding it myself for the past few weeks in some projects and it fits nicely. I’ve discovered (and fixed) a lot of flaws and bugs along the way, so overall it has been a good experience.

I started a new site to be the dedicated home for CobaltMVC, which also happens to be on the same domain as my new website, at cobaltmvc.hugoware.com.

The site isn’t complete yet – I have a lot of documentation to write along with getting additional work done on my ‘personal’ part of the website, but overall it is a good example of what the finished site will look like.

Additionally, the site itself is powered by CobaltMVC… what a coincidence!

Written by hugoware

July 28, 2010 at 7:41 pm

Almost Sorta Real Dynamic in .NET

with 8 comments

This post discusses the basics of writing your own dynamic type – If you’re interested in the finished code make sure to download the source.

The new dynamic keyword is a great way to create and modify a dynamic object in your .NET code – For example, check out this bit of code.

dynamic counter = new {
    sent = 0,
    received = 0
};
counter.sent++;

… Oh… wait… That doesn’t actually work…

That’s because even though you have an object declared as dynamic, it is still just the same old object it always was under the hood. Maybe not the dynamic utopia we were expecting. Seems like plain ol’ Reflection with a slightly cleaner syntax.

Bummer…

However, Microsoft was awesome enough to actually allow us to create our own dynamic types by simply inheriting from the DynamicObject class. This post looks at how we can create a semi-dynamic object by handling the binding methods ourselves.

[Source Code: Dynamic.cs]

Our goal is to create an object that we can add, remove and change values on the fly. It ends up being a little easier than we expect. Let’s look at the minimum code we are going to need to get started.

public class SimpleDynamic : DynamicObject {

    //contains the values to use
    private Dictionary<string, object> _Values = new Dictionary<string, object>();

    //handles getting values from our object
    public override void TryGetMember(GetMemberBinder binder, out object result) {
        //...
    }

    //handles assigning values to our object
    public override bool TrySetMember(SetMemberBinder binder, object value) {
        //...
    }

}

Note: If you downloaded the source code above you might be wondering why these examples don’t look the same. The source code is the complete Dynamic class while this post only goes over the basics of using the DynamicObject class.

In order to create our dynamic object we must handle getting and setting values. We can use a simple Dictionary<string,object> to hold our values until we need them.

//handles getting values from our object
public override void TryGetMember(GetMemberBinder binder, out object result) {
    return this._Values.TryGetValue(binder.name, out result);
}

//handles assigning values to our object
public override bool TrySetMember(SetMemberBinder binder, object value) {
    this._Values.Remove(binder.name);
    if (value is object) { this._Values.Add(binder.name, value); }
    return true;
}

Not much code, but now our dynamic object is a little more dynamic than it was before. We can now work with properties a lot easier.

//create the new object
dynamic simple = new SimpleDynamic();

//add and update some values
simple.red = "#f00";
simple.green = "#0f0";
simple.count = 10;
simple.add = new Action<int>(value => simple.count += value);

//and check the values
Console.WriteLine(simple.red); // #f00
Console.WriteLine(simple.green); // #0f0
Console.WriteLine(simple.count); // 10

//invoke methods
simple.add(5);
Console.WriteLine(simple.count); // 15

Of course this class isn’t that helpful since it’s only regular Dictionary without string indexes but it is interesting to see how you can make a ‘dynamic’ object with only a few lines of code.

As for the included source code, it has a few extra features that this class doesn’t have.

  • Use Anonymous Types directly to build out entire objects.
  • Support for the += operator.
  • Enumeration through member names.
  • String indexes (for both single and nested properties).

Here are a few examples the Dynamic.cs class can do.

//create using anonymous types (and nested anonymous types)
dynamic info = new Dynamic(new {
    name = "Hugo",
    age = 30,
    settings = new {
        color = "orange",
        homepage = "website.com"
    }});

//add values using +=
info.create = new { value = false; }
info.nested.value.allowed = 55;

//enumeration of properties
foreach(string prop in info) {
    Console.WriteLine("{0}: {1}", prop, info[prop]);
}

I’d caution against using this a lot in your projects, but it is really interesting to see the kind of control Microsoft has built into the new DynamicObject class.

[Source Code: Dynamic.cs]

Written by hugoware

July 15, 2010 at 12:32 am

CobaltMVC – Custom Controls and Dynamic HTML

with one comment

CobaltMVC is a server side templating frameworks that works a lot like jQuery. You can use it with both ASP.NET MVC and WebForms – (Watch the introduction video)

So far all of the CobaltMVC examples that have been posted have involved selecting existing elements on the page and making changes to them. However, there are times you’d like to generate new elements or wrap the same markup in a reusable control and attach it to the page.

Controls in CobaltMVC are just CobaltElements with properties and methods that you can use to define the behavior of an element. Because of this, a control can be selected against and modified by external selectors. This means that any control can be adjusted and tweaked for your individual needs.

Want to learn more? Check out the screen cast below that explains some of the interesting things you can do with custom controls and dynamically generated HTML elements.

[Watch The Screencast!]

Written by hugoware

June 4, 2010 at 9:52 am