Dictionary Extensions: Define useful extensions to play safe January 18, 2012
Posted by codinglifestyle in C#, CodeProject.Tags: dictionary, extension, extension methods, key, safe, templates, value
add a comment
if (searchCriteria.ContainsKey(key) && !string.IsNullOrEmpty(searchCriteria[key])) searchTerm = searchCriteria[key];
Ever have a dictionary or similar data structure and your code has many repeated checks to pull the value when in reality you’d be happy with a default value like null or string.Empty? Well, consider the following extension to Dictionary:
public static class DictionaryExtensions { public static TValue GetSafeValue<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key) { TValue result = default(TValue); dictionary.TryGetValue(index, out result); return result; } }
Let’s you do:
Dictionary bob = new Dictionary(); string safe = bob.GetSafeValue(100); System.Diagnostics.Trace.WriteLine(safe);
where safe defaults to “” as it hasn’t been added. Stop! I know what you’re going to say and I thought of that too. You can control the default value as well:
public static class DictionaryExtensions { /// <summary> /// Gets the safe value associated with the specified key. /// </summary> /// <typeparam name="TKey">The type of the key.</typeparam> /// <typeparam name="TValue">The type of the value.</typeparam> /// <param name="dictionary">The dictionary.</param> /// <param name="key">The key of the value to get.</param> public static TValue GetSafeValue<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key) { return dictionary.GetSafeValue(key, default(TValue)); } /// <summary> /// Gets the safe value associated with the specified key. /// </summary> /// <typeparam name="TKey">The type of the key.</typeparam> /// <typeparam name="TValue">The type of the value.</typeparam> /// <param name="dictionary">The dictionary.</param> /// <param name="key">The key of the value to get.</param> /// <param name="defaultValue">The default value.</param> public static TValue GetSafeValue<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue) { TValue result; if (key == null || !dictionary.TryGetValue(key, out result)) result = defaultValue; return result; } }
Let’s you do:
Dictionary bob = new Dictionary(); string safe = bob.GetSafeValue(100, null); System.Diagnostics.Trace.WriteLine(safe);
where safe is null.
There’s obviously something wrong with me because I still think this stuff is cool.
I’m developing a nice little set of extensions at this point. Often it seems like overkill to encapsulate handy functions like these in a class. I had started by deriving a class from Dictionary<TKey, TValue> but changed over to the above.
FindControl: Recursive DFS, BFS, and Leaf to Root Search with Pruning October 24, 2011
Posted by codinglifestyle in ASP.NET, C#, CodeProject, jQuery.Tags: ASP.NET, BFS, DFS, extension methods, FindControl, jQuery, pruning, tree
add a comment
I have nefarious reason for posting this. It’s a prerequisite for another post I want to do on control mapping within javascript when you have one control which affects another and there’s no good spaghetti-less way to hook them together. But first, I need to talk about my nifty FindControl extensions. Whether you turn this in to an extension method or just place it in your page’s base class, you may find these handy.
We’ve all used FindControl and realized it’s a pretty lazy function that only searches its direct children and not the full control hierarchy. Let’s step back and consider what we’re searching before jumping to the code. What is the control hierarchy? It is a tree data structure whose root node is Page. The most common recursive FindControl extension starts at Page or a given parent node and performs a depth-first traversal over all the child nodes.
Search order: a-b-d-h-e-i-j-c-f-k-g
/// <summary> /// Recurse through the controls collection checking for the id /// </summary> /// <param name="control">The control we're checking</param> /// <param name="id">The id to find</param> /// <returns>The control, if found, or null</returns> public static Control FindControlEx(this Control control, string id) { //Check if this is the control we're looking for if (control.ID == id) return control; //Recurse through the child controls Control c = null; for (int i = 0; i < control.Controls.Count && c == null; i++) c = FindControlEx((Control)control.Controls[i], id); return c; }
You will find many examples of the above code on the net. This is the “good enough” algorithm of choice. If you have ever wondered about it’s efficiency, read on. Close you’re eyes and picture the complexity of the seemingly innocent form… how every table begets rows begets cells begets the controls within the cell and so forth. Before long you realize there can be quite a complex control heirarchy, sometimes quite deep, even in a relatively simple page.
Now imagine a page with several top-level composite controls, some of them rendering deep control heirachies (like tables). As the designer of the page you have inside knowledge about the layout and structure of the controls contained within. Therefore, you can pick the best method of searching that data structure. Looking at the diagram above and imagine the b-branch was much more complex and deep. Now say what we’re trying to find is g. With depth-first you would have to search the entiretly of the b-branch before moving on to the c-branch and ultimately finding the control in g. For this scenario, a breadth-first search would make more sense as we won’t waste time searching a complex and potentially deep branch when we know the control is close to our starting point, the root.
Search order: a-b-c-d-e-f-g-h-i-j-k
/// <summary> /// Finds the control via a breadth first search. /// </summary> /// <param name="control">The control we're checking</param> /// <param name="id">The id to find</param> /// <returns>If found, the control. Otherwise null</returns> public static Control FindControlBFS(this Control control, string id) { Queue<Control> queue = new Queue<Control>(); //Enqueue the root control queue.Enqueue(control); while (queue.Count > 0) { //Dequeue the next control to test Control ctrl = queue.Dequeue(); foreach (Control child in ctrl.Controls) { //Check if this is the control we're looking for if (child.ID == id) return child; //Place the child control on in the queue queue.Enqueue(child); } } return null; }
Recently I had a scenario where I needed to link 2 controls together that coexisted in the ItemTemplate of a repeater. The controls existed in separate composite controls.
In this example I need to get _TexBoxPerformAction’s ClientID to enable/disable it via _ChechBoxEnable. Depending on the size of the data the repeater is bound to there may be hundreds of instances of the repeater’s ItemTemplate. How do I guarantee I get the right one? The above top-down FindControl algorithms would return he first match of _TextBoxPerformAction, not necessarily the right one. To solve this predicament, we need a bottom-up approach to find the control closest to us. By working our way up the control hierarchy we should be able to find the textbox within the same ItemTemplate instance guaranteeing we have the right one. The problem is, as we work our way up we will be repeatedly searching an increasingly large branch we’ve already seen. We need to prune the child branch we’ve already seen so we don’t search it over and over again as we work our way up.
To start we are in node 5 and need to get to node 1 to find our control. We recursively search node 5 which yields no results.
Next we look at node 5’s parent. We’ve already searched node 5, so we will prune it. Now recursively search node 4, which includes node 3, yielding no results.
Next we look at node 4’s parent. We have already searched node 4 and its children so we prune it.
Last we recursively search node 2, which includes node 1, yielding a result!
So here we can see that pruning saved us searching an entire branch repeatedly. And the best part is we only need to keep track of one id to prune.
/// <summary> /// Finds the control from the leaf node to root node. /// </summary> /// <param name="ctrlSource">The control we're checking</param> /// <param name="id">The id to find</param> /// <returns>If found, the control. Otherwise null</returns> public static Control FindControlLeafToRoot(this Control ctrlSource, string id) { Control ctrlParent = ctrlSource.Parent; Control ctrlTarget = null; string pruneId = null; while (ctrlParent != null && ctrlTarget == null) { ctrlTarget = FindControl(ctrlParent, id, pruneId); pruneId = ctrlParent.ClientID; ctrlParent = ctrlParent.Parent; } return ctrlTarget; } /// <summary> /// Recurse through the controls collection checking for the id /// </summary> /// <param name="control">The control we're checking</param> /// <param name="id">The id to find</param> /// <param name="pruneClientID">The client ID to prune from the search.</param> /// <returns>If found, the control. Otherwise null</returns> public static Control FindControlEx(this Control control, string id, string pruneClientID) { //Check if this is the control we're looking for if (control.ID == id) return control; //Recurse through the child controls Control c = null; for (int i = 0; i < control.Controls.Count && c == null; i++) { if (control.Controls[i].ClientID != pruneClientID) c = FindControlEx((Control)control.Controls[i], id, pruneClientID); } return c; }
Now we have an efficient algorithm for searching leaf to root without wasting cycles searching the child branch we’ve come from. All this puts me in mind jQuery’s powerful selection capabilities. I’ve never dreamed up a reason for it yet, but searching for a collection of controls would be easy to implement and following jQuery’s lead we could extend the above to search for far more than just an ID.
Custom Attributes with Extension Methods: Resource Key July 4, 2011
Posted by codinglifestyle in C#, CodeProject.Tags: attributes, custom, extension methods, generics, resource, resource key
add a comment
I picked up this technique in my last job to use a custom attribute to contain a resource key. The biggest benefit was all the enums in the system used this attribute which provided a way to translate that enum to text. Take a look at a sample enum:
public enum Mode { [AttributeResourceKey("lblInvalid")] Invalid, [AttributeResourceKey("lblReview")] Review, [AttributeResourceKey("lblCheckout")] Checkout, [AttributeResourceKey("lblOrdered")] Ordered }
Each enum uses the AttributeResourceKey to specify the resource key defined in the resx file. Combined with an extension method we can extend the enum itself to allow us to execute the following:
public void DoOperation(Mode mode) { Log.Info(GetResourceString(mode.ResourceKey())); ... }
The C++ head in me thinks, “why are we using reflection when a static function in a helper class could contain a switch statement to convert the enum to the resource key?”. Technically this is sufficient and faster. However, the C# head in me loves the idea that the enum and the resource key are intimately tied together in the same file. There is no helper function to forget to update. The penalty of reading an attribute is a small price to pay to keep the enum and resource key together in order to increase overall maintainability.
So the first thing I am going to do is define a simple interface for my custom attributes.
public interface IAttributeValue<T> { T Value { get; } }
All this interface does is define that the custom attribute class itself will define a property called Value of type T. This will be useful when using the generic method, below, for pulling the attribute. Next we define the custom attribute class itself.
public sealed class AttributeResourceKey : Attribute, IAttributeValue<string> { private string _resourceKey; public AttributeResourceKey(string resourceKey) { _resourceKey = resourceKey; } #region IAttributeValue<string> Members public string Value { get { return _resourceKey; } } #endregion }
Notice how simple the above class is. We have a constructor taking a string and a property called Value which returns said string. Now let’s look at the generic method for pulling the attribute.
public static class AttributeHelper { /// <summary> /// Given an enum, pull out its attribute (if present) /// </summary> public static TReturn GetValue<TAttribute, TReturn>(object value) where TAttribute: IAttributeValue<TReturn> { FieldInfo fieldInfo = value.GetType().GetField(value.ToString()); object[] attribs = fieldInfo.GetCustomAttributes(typeof(TAttribute), false); TReturn returnValue = default(TReturn); if (attribs != null && attribs.Length > 0) returnValue = ((TAttribute)attribs[0]).Value; return returnValue; } }
The code above is the heart of code. It uses generics so you need only define this code once in a static class. By passing the attribute and return type we can extract our Value defined by IAttributeValue<TReturn>. Using the where constraint on TAttribute allows the generic method to know this type defines a property called Value of type TReturn. This exposes the true power of generics as without this constraint the method could only presume TAttribute is nothing more than an object. This might tempt you to wrongly cast TAttribute in order to access it’s properties inviting an exception only seen at runtime.
Now to define our extension method, to be placed in a common namespace, to extend all enums with the ResourceKey() method.
public static class EnumerationExtensions { /// <summary> /// Given an enum, pull out its resource key (if present) /// </summary> public static string ResourceKey(this Enum value) { return AttributeHelper.GetValue<AttributeResourceKey, string>(value); } }
Thanks to the generic attribute helper the above extension method looks trivial. We simply use the helper to return the resource key and now we’ve extended all our enums to have this useful property.