Showing posts with label .NET Nuggets. Show all posts
Showing posts with label .NET Nuggets. Show all posts

March 26, 2008

.NET Code Performance Measurement

When improving the performance of your code, it's often usefull to know how fast (or slow) your code is running. I was going to show you a neat little class that I've been using for years that wraps some Win32 API functions, but my pre-blogging research has revealed that my approach is a bit outdated. Since .NET 2.0 there has been just such a wrapper class baked into the framework. It's the System.Diagnostics.Stopwatch class. It's use is simple:


Stopwatch timer = new Stopwatch();
timer.Start();

...Code to evaluate goes here...

timer.Stop();
double elapsed = timer.ElapsedMilliseconds;

In addition to getting the ElapsedMilliseconds, you can also access the Elapsed property to get a timespan or ElapsedTicks to get the ticks.

November 26, 2007

ICustomTypeDescriptor

Recently I had what is probably a very strange need, but I doubt I'm the first one to have it. I essentially had a two dimensional array, more specifically an object of type List<Dictionary<string,string>>, that I needed to bind to a GridView. I couldn't use a custom collection because the schema of the data structure could be just about anything (the GridView columns were being built at runtime). I won't get into the details of why I was using a List of Dictionary objects as opposed to simply using a DataTable, but for the sake of simplicity let's just say it was the only option I had. Now what I needed to do with this collection was to bind it to the GridView, using the keys in the Dictionary as the DataField for the columns.

My first thought..."maybe it'll just work". I knew I was being overly optimistic, but I had to try anyway, and I received an error message of "'KeyName' is not a member of Dictionary", or something to that effect. Now I knew that the ability to bind to a dynamic schema based on column names existed in the DataTable, so I opened up Reflector and took a peek under the hood. After a few minutes of rummaging around I came across the golden treasure that is ICustomTypeDescriptor.

If you were to think of a custom class as a spy for some reason, then ICustomTypeDescriptor would be like a disguise that allows your object to masquarade behind enemy lines pretending to be something it's not (I've been playing a lot of Team Fortress 2 lately). On a more technical level, any time your object is accessed via reflection, in databinding for example, ICustomTypeDescriptor allows you to define the facade that your object exposes at runtime. So let's say I have a column in a GridView that is bound to the "ID" property of my custom object. If my object doesn't have an "ID" property then we get an error, but if my object implements ICustomTypeDescriptor then I can trick the calling code into thinking it has a property called "ID", and whenever the value of that property is requested my object can run whatever custom logic I write in order to return a valid value.

Let's get to the code. We need to start by abstracting that generic dictionary into a custom class that we can slap ICustomTypeDescriptor on. Here's what the end result looks like:

public class MyCustomClass : Dictionary<string, string>, ICustomTypeDescriptor
{
private PropertyDescriptorCollection m_PropertyDescriptorCollectionCache;

AttributeCollection ICustomTypeDescriptor.GetAttributes()
{
return new AttributeCollection(null);
}

string ICustomTypeDescriptor.GetClassName()
{
return null;
}

string ICustomTypeDescriptor.GetComponentName()
{
return null;
}

TypeConverter ICustomTypeDescriptor.GetConverter()
{
return null;
}

EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
{
return null;
}

PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
{
return null;
}

object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
{
return null;
}

EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
{
return new EventDescriptorCollection(null);
}

EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
{
return new EventDescriptorCollection(null);
}

PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
{
if (m_PropertyDescriptorCollectionCache == null)
{
PropertyDescriptor[] properties = new PropertyDescriptor[this.Count];
int i = 0;
foreach (string key in this.Keys)
{
properties[i] = new MyCustomClassPropertyDescriptor(key);
i++;
}
m_PropertyDescriptorCollectionCache = new PropertyDescriptorCollection(properties);
}
return m_PropertyDescriptorCollectionCache;
}

PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
{
return ((ICustomTypeDescriptor)this).GetProperties(null);
}

object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
{
return this;
}
}

Mostly it's a lot of methods that I didn't need for the purpose of databinding, so I just return null. The heart of the whole thing is the GetProperties method. Note that it is overloaded in the interface to allow for filtering by certain attribute types. I didn't have a need for this so I didn't write the code to do it, but you're welcomed to if you like. Anyway, the purpose of this method is to return a PropertyDescriptorCollection that describes all of the properties of the object. In my case I needed to expose every key in the Dictionary as a property that I could bind to, so that's what it does.

Now if you're paying attention you'll notice that it's slightly more complicated than that. We also have to create another class that contains the logic to retrieve a value from the dictionary when a property is requested:

public class MyCustomClassPropertyDescriptor : PropertyDescriptor
{
public ResponsePropertyDescriptor(string key) : base(key, null)
{

}

public override bool CanResetValue(object component)
{
return true;
}

public override Type ComponentType
{
get { return typeof(Dictionary<string, string>); }
}

public override object GetValue(object component)
{
return ((Dictionary<string, string>)component)[base.Name];
}

public override bool IsReadOnly
{
get { return false; }
}

public override Type PropertyType
{
get { return typeof(string); String.IsNullOrEmpty(string value); }
}

public override void ResetValue(object component)
{
((Dictionary<string, string>)component)[base.Name] = string.Empty;
}

public override void SetValue(object component, object value)
{
((Dictionary<string, string>)component)[base.Name] = value.ToString();
}

public override bool ShouldSerializeValue(object component)
{
return false;
}
}

This is a pretty simple class that inherits from PropertyDescriptor. When we instantiate it we pass the value of the Dictionary key, which becomes the name of the fake property we are exposing.

So our problem is solved. As the GridView is being bound, it makes a request for the property of MyCustomClass definded in the DataField. Even though that property doesn't actually exist in MyCustomClass, because we have implemented ICustomTypeDescriptor everything is ok. The request gets passed on to the GetValue method of MyCustomClassPropertyDescriptor, which uses the requested property name to retrieve the value from the Dictionary object by key. Very simple and very cool.

January 3, 2007

.NET Nuggets

With all the flashy new features of ASP.NET 2.0 it's easy to overlook the little things that actually help out in your daily coding. Here's a couple that I use quite often:

  1. String.IsNullOrEmpty(string value)

    This method does exactly what it says, returns true if a given string is either null or empty. A quick look in reflector reveals that it does this by properly checking the length of the string as opposed to comparing it to String.Empty:



    public static bool IsNullOrEmpty(string value)
    {
    if (value != null)
    {
    return (value.Length == 0);
    }
    return true;
    }


  2. int.TryParse(string s, out int result)

    This method takes a string and attempts to convert it to an integer, returning the result through an output parameter. If the conversion is successful, the result will be the appropriate integer, otherwise the result will be zero. The conversion will fail if the input parameter is null, not a properly formatted integer, or falls outside the range of an Int32 type.


    I looked at this with Reflector, and it's a bit too complicated to post here, but the cool thing is that it does it's thing without ever using a try/catch. This method definitely comes in handy when you need to get integer values from an untrusted source like the querystring.