2010-01-06

Enums and String values

Recently, I had the need to set string values for enums, instead of using int values. Browsing the web, I came to Stefan Sedich’s blog, which had a very interesting article on creating string value attributes for enums. The article explained how to assign a custom string attribute to each enum value, and then how to get that string value from the enum by using reflection.

The article, as I said, was great, but it was missing one thing: working the other way around. I mean, it explained how to get the string value from the enum, but not how to get the enum value from the string. I needed both "ends" of the feature, With the help of a CodeProject article I found, I got to implement it succesfully.

So, to tell the whole story, here's how it basically works:

First, create a custom Attribute (a class that inherits the Attribute class)

  1: public class StringValueAttribute : Attribute
  2: {
  3:     /// <summary>
  4:     /// Holds the stringvalue for a value in an enum.
  5:     /// </summary>
  6:     public string StringValue { get; protected set; }
  7: 
  8:     /// <summary>
  9:     /// Constructor used to init a StringValue Attribute
 10:     /// </summary>
 11:     /// <param name="value"></param>
 12:     public StringValueAttribute(string value)
 13:     {
 14:         this.StringValue = value;
 15:     }
 16: }
Second, add the attribute to each one of your enum values:
  1: public enum UserState
  2: {
  3:     [StringValueAttribute("A")]
  4:     Active,
  5:     [StringValueAttribute("I")]
  6:     Inactive,
  7:     [StringValueAttribute("S")]
  8:     StandBy
  9: } 

Now, to get the associated string for a given enum value, you create an Extension Method for the Enum type:

  1: public static string GetStringValue(this Enum value)
  2: {
  3:     // Get the type
  4:     Type type = value.GetType();
  5: 
  6:     // Get fieldinfo for this type
  7:     FieldInfo fieldInfo = type.GetField(value.ToString());
  8: 
  9:     // Get the stringvalue attributes
 10:     var attribs = 
 11:         fieldInfo.GetCustomAttributes(typeof(StringValueAttribute), false) 
 12:         as StringValueAttribute[];
 13: 
 14:     // Return the first if there was a match.
 15:     return attribs.Length > 0 ? attribs[0].StringValue : null;
 16: }

To get the string value for the enum, we just needed to call the extension method:

  1: string state = UserState.Inactive.GetStringValue();

As I already said. This was all posted in Stefan Sedich’s article.

Now to go the other way around, here's what we need to do:

Just as in the first extension method was for the enum type and returned a string, our new one will have to be for the string type and return an enum. Actually, because the method will be generic to any enum type, we'll return an object, which will have to be casted by the caller to the appropriate type. This is the code:

  1: public static object GetEnumStringValue(this string value, 
  2:     Type enumType, bool ignoreCase)
  3: {
  4:     object result = null;
  5:     string enumStringValue = null;
  6:     if (!enumType.IsEnum)
  7:         throw new ArgumentException
  8:             ("enumType should be a valid enum");
  9: 
 10:     foreach (FieldInfo fieldInfo in enumType.GetFields())
 11:     {
 12:         var attribs = 
 13:             fieldInfo.GetCustomAttributes(typeof(StringValueAttribute), false) 
 14:             as StringValueAttribute[];
 15:         //Get the StringValueAttribute for each enum member
 16:         if (attribs.Length > 0)
 17:             enumStringValue = attribs[0].StringValue;
 18: 
 19:         if (string.Compare(enumStringValue, value, ignoreCase) == 0)
 20:             result = Enum.Parse(enumType, fieldInfo.Name);
 21:     }
 22: 
 23:     return result;
 24: }

To call it, we'll go with something like this:

  1: UserState enu = (UserState)"A".GetEnumStringValue(typeof(UserState), true);
There you go, hope you find it useful.

Adding methods to existing types with Extension Methods

Ever felt like one of the types you work with could have used a couple of extra methods? Maybe you’d want to add to the string type a method called ToHyperLink, which will add HTML tags to your string to make it a valid HyperLink. In other words, if your string is

http://msdn.microsoft.com

and you call the method, you'll get something like

<a href='http://msdn.microsoft.com'>http://msdn.microsoft.com</a>

We basically have two approaches here: one, create a class that inherits string, and implement the method there. This will mean that if you wanted to use the method on an object, it'll have to be declared as your new type, not string. The second approach is to use Extension Methods.  With this technique, you get the possibility to "add" methods to existing types without having to create derived classes, thus extending their functionality.

Extension method have to be implemented inside a static class, and of course have to be static themselves. They could return any type you want, and have to have at least one parameter, of the type you want to extend, preceded by the word this. Check out this example:

  1: public static class Extensions
  2: {
  3:     public static string ToHyperLink(this string url)
  4:     {
  5:         string hl = string.Format("<a href='{0}'>{0}</a>", url);
  6:         return hl;
  7:     }
  8: }

In the above code, we created an extension method for the string type called ToHyperLink, which returns another string. It's that simple. As said before, the catch here is just to add the keyword this, and to make both the method and its class static.

Now, if we wanted to use it, we jus need a using reference to whatever the classes' namespace is, and call it just like we call any of the other string methods:

  1: //Here call the extension method an a variable
  2: string a = "http://msdn.microsoft.com";
  3: a = a.ToHyperLink();
  4: //Here we call the extension method on a plain string
  5: string b = "http://hugonne.blogspot.com".ToHyperLink();

Notice line 5? You can call the extension method directly on a string value rather than a variable. This is something we couldn't have achieved with inheritance.

Extension methods can also take additional parameters. Let's say we want to create an overload for the method, which takes the text for the HyperLink. We'd add a method to our class like this:

  1: public static string ToHyperLink(this string url, string linkText)
  2: {
  3:     string hl = string.Format("<a href='{0}'>{1}</a>", url, linkText);
  4:     return hl;
  5: }

Calling the method is just as simple:

  1: string c = "http://msdn.microsoft.com";
  2: c = c.ToHyperLink("Go to MSDN");
So, extension methods are are quick way to expand the functionality of our existing types. Nevertheless, it's always good to say you should try and use them only for simple operations. If you require some sort of more complex operations, it'll be always better to use inheritance, and make your own specialized types.

One final thing: extension methods only work in the .NET Framework 3.5.

2009-10-16

Reference types

Quick reminder: Any object you have to instantiate (e.g. create with the new keyword) is what’s called a Reference Type. It means that, when used as a method parameter, it will always be treated as a reference parameter (ref in C#, ByRef in VB).

In other words, this is redundant:

  1: void ModifyData(ref DataSet data)
  2: {
  3:     //....
  4: }

Because DataSet is a reference type, the ref keyword in the above examples serves no use. 

Opposite to reference types are Value Types, like an int or a string. They have to specify the ref keyword in the parameter if they want to be treated as such.

Here’s a good article on reference and value types.

See ya.

2009-10-14

Setting an enum value from a string

In a piece of code I was reviewing I saw that they wanted to set the value for an enum from a string, and what they did was to create a large method with a big switch statement, setting the correct enum value for each case. Something like:

  1: enum Operators
  2: {
  3:    GreaterThan,
  4:    Equals,
  5:    LessThan
  6: }
  7: 
  8: Operators GetOperatorFromString(string s)
  9: {
 10:    switch(s.ToUpper())
 11:    {
 12:       case "GREATERTHAN":
 13:          return Operators.GreaterThan;
 14:       case "EQUALS":
 15:          return Operators.Equals;
 16:       case "LESSTHAN":
 17:          return Operators.LessThan;
 18:    }
 19: }

Now, this could be kind of simple if your enum doesn’t have many values, but if we’re talking about very large lists, then we have a problem…

Well, the solution for this is actually very simple, by using System.Enum.Parse, which has the following signature:

object Enum.Parse(System.Type enumType, string value, bool ignoreCase);

So, you can write the following:

  1: enum Operators
  2: {
  3:    GreaterThan,
  4:    Equals,
  5:    LessThan
  6: }
  7: 
  8: // ...
  9: 
 10: Operators o = (Operators)Enum.Parse(typeof(Operators), "greaterthan", true);

Notice that, since we have the ingnoreCase parameter set to true,  we can use the string in any kind of case. If the string value doesn’t match any of the enum values, an exception of type ArgumentException will be raised.

2009-10-06

Quick Windows tips

This has nothing to do with programming, and probably many people already know it, but what the hell. It might be a nice thing to teach your end users.

First, to get a screenshot of just the active window, instead of your whole screen, just press the Alt and PrintScreen keys together. That way, you’ll copy the screenshot to your clipboard, but you’ll not get your task bar, and you wouldn’t have to go to Paint to chop your image.

Second, to get the text of a message box shown by an app, just make sure that box is active, and press Ctrl + C. Windows will automatically copy the title, message and buttons text to the clipboard. You’ll get something like this:

---------------------------
Exit
---------------------------
Are you sure you want to quit?
---------------------------
Yes   No  
---------------------------

2009-09-18

Difference between Eval and Bind databinding expressions

Hi. I just faced a problem where I was using an ASP.NET GridView control which was bound to a SqlDataSource. One of the bound columns was “User” and, of course, brought the user name. What I wanted to do was to add a HyperLink to that text, so that instead of just saying “Mark”, with would show up as a link to the UserDetalis page, passing “Mark” as a QueryString variable. Something like this:

  1: <a href='UserDetails.aspx?user=Mark>Mark</a>

So, because I had a databound GridView, I just had to make the “User” column a template column and replace the standard label (Label1 in this code)

  1: <asp:GridView ID="myGridView" runat="server" 
  2:     DataSourceID="myDataSource">
  3:     <Columns>
  4:         <asp:TemplateField HeaderText="User" SortExpression="User">
  5:             <ItemTemplate>
  6:                 <asp:Label ID="Label1" runat="server" Text='<%# Bind("User") %>' />
  7:             </ItemTemplate>
  8:         </asp:TemplateField>
  9:     </Columns>
 10: </asp:GridView>

by a HyperLink (HyperLink1 in this code), and set its NavigateUrl property to the new value, which held the whole hyperlink HTML text. So the first thing that came to my mind was to do something like this:

  1: <asp:HyperLink ID="HyperLink1" runat="server" Text='<%# Bind("User") %>'
  2:     NavigateUrl='<%# String.Format("UserDetails.aspx?user={0}", Bind("User")) %>' />

But it turned out I got a runtime error that said: The name 'Bind' does not exist in the current context. If I used Eval instead of Bind:

  1: <asp:HyperLink ID="HyperLink1" runat="server" Text='<%# Eval("User") %>'
  2:     NavigateUrl='<%# String.Format("UserDetails.aspx?user={0}", Eval("User")) %>' />

It worked like a charm.

OK, I got my problem solved, but now I needed to know the difference between both, and specifically why it worked with one and not the other. Well, here it is:

Eval is one way, for read-only purposes, as Bind is two way, for read-write operations. Eval is actually a static protected method defined on the TemplateControl class, from which the Page class is derived, and it returns a string. Because it’s a real method, you could combine it with other statements, like the string.Format we just used. Bind, on the other hand, is not an actual method, it’s a new ASP.NET 2.0 databinding keyword, so of course, it can’t be used with other method calls or stuff. Bottom line is, if you need to only read the text, and perhaps change it a little, use Eval. If you need to write back to the db or something like that, use Bind.

Hope you got it clear. This article has some more deep definitions, which you might find useful as well.

2009-09-15

Creating design-time compatible properties and events, part 2

Hi all. In part 1 of this article, we learned how to make our simple properties show up in the properties window at design-time, so that they looked just like the built in ones that .NET controls have. Here, in part 2, we’ll discuss how to make your events show up, as well as some more advanced stuff, like adding custom lists.

First, events, opposite to Properties, don’t show by default in the properties Windows (that is, they’re not Browsable by default), so in order to show them all we need to do is to set that property to true:

  1: [Browsable(true)]
  2: public event EventHandler MyEvent;

It’s all it takes.

Now, the fun part. Let’s add some custom lists. Suppose we want to add a property to our NiceTextBox called SomeList, which can hold any of these four values: One, Two, Three and Four. There are several ways to achieve this, but I’m gonna take the simple way and use a string. So, first, we’ll have to create a “converter” class. Converter classes are used to convert specific types to and from other different types. Since we’re using a string, we’ll need to create a class that inherits System.ComponentModel.StringConverter. We’'ll use this to convert my list to and from a string.

  1: public class SomeListConverter : StringConverter
  2: {
  3:     //Values list. You could bring this from a database or so
  4:     private readonly string[] values = new[] { "One", "Two", "Three", "Four" };
  5: 
  6:     public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
  7:     {
  8:         //When true, only a value from the list can be selected
  9:         return true;
 10:     }
 11: 
 12:     public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
 13:     {
 14:         //Return the list as a collection of standard values.
 15:         //This is the method the designer will use to pupulate the list
 16:         return new StandardValuesCollection(values);
 17:     }
 18: 
 19:     public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
 20:     {
 21:         //When false, the list will be editable, meaning that the user could type 
 22:         //a value as well. When true, the list will be read-only
 23:         return true;
 24:     }
 25: }

Now, let’s create the property. We’ll have to use the TypeConverter attribute to tell the property what class it should use to convert our List (of type StandardValuesCollection) to and from a string:

  1: [TypeConverter(typeof(SomeListConverter))]
  2: [Category("Custom properties"), DefaultValue(""), Description("Some custom list used")]
  3: public string SomeList { get; set; }

The result will be pretty neat:

OK, so that’s it for simple lists. But what if one of our custom properties needs to be set through a more complex class? Let’s take a look at the following example, we’ll create a property called Version, which will have all four parts of a regular assembly version: Major, Minor, Build and Private. We’ll do it so that the user can set the version value directly (something like 2.1.0.17), or he can set the value for each part separately. That kind of behavior, like the one we see in common properties as Location and Size, is achieved through something called expandable objects, specifically by using the ExpandableObjectConverter class.

First, we’ll create an ApplicationVersion class:

  1: public class ApplicationVersion
  2: {
  3:     public short Major { get; set; }
  4: 
  5:     public short Minor { get; set; }
  6: 
  7:     public short Build { get; set; }
  8: 
  9:     public short Private { get; set; }
 10: }

This class we’ll represent the type of our Version property (which we’ll construct later). Now, we’ll have to create the converter. Like said before, because this property will be an expandable object, we’ll have to inherit the ExpandableObjectConverter class:

  1: internal class ApplicationVersionConverter : ExpandableObjectConverter
  2: {
  3:     public override bool CanConvertTo(ITypeDescriptorContext context, 
  4:         Type destinationType)
  5:     {
  6:         //This will indicate if the Converter can convert the object TO the 
  7:         //specified type. In this case, ApplicationVersion to string
  8:         return destinationType == typeof(ApplicationVersion) || 
  9:             base.CanConvertTo(context, destinationType);
 10:     }
 11: 
 12:     public override bool CanConvertFrom(ITypeDescriptorContext context, 
 13:         Type sourceType)
 14:     {
 15:         //This will indicate if the Converter can convert the object FROM the 
 16:         //specified type. In this case, string to ApplicationVersion
 17:         return sourceType == typeof(String) || 
 18:             base.CanConvertFrom(context, sourceType);
 19:     }
 20: 
 21:     public override object ConvertFrom(ITypeDescriptorContext context, 
 22:         System.Globalization.CultureInfo culture, object value)
 23:     {
 24:         //This will implement the logic to convert from string to object. 
 25:         /It will be used when the user directly enters the version value 
 26:         //(2.0.4.17) instead of setting each part individually
 27:         if (value is string)
 28:             try
 29:             {
 30:                 string s = value.ToString();
 31:                 string[] versionParts = s.Split('.');
 32:                 if (versionParts.Length > 0)
 33:                 {
 34:                     var version = new ApplicationVersion();
 35:                     if (versionParts[0] != null)
 36:                         version.Major = Convert.ToInt16(versionParts[0]);
 37:                     if (versionParts[1] != null)
 38:                         version.Minor = Convert.ToInt16(versionParts[1]);
 39:                     if (versionParts[2] != null)
 40:                         version.Build = Convert.ToInt16(versionParts[2]);
 41:                     if (versionParts[3] != null)
 42:                         version.Private = Convert.ToInt16(versionParts[3]);
 43:                     return version;
 44:                 }
 45:             }
 46:             catch (Exception)
 47:             {
 48:                 throw new ArgumentException(
 49:                     string.Format(
 50:                         "The value {0} isn't a valid Version number", value));
 51:             }
 52:         return base.ConvertFrom(context, culture, value);
 53:     }
 54: 
 55:     public override object ConvertTo(ITypeDescriptorContext context, 
 56:         System.Globalization.CultureInfo culture, 
 57:         object value, Type destinationType)
 58:     {
 59:         //This will implement the logic to convert from object to string. 
 60:         //It serves the exact opposite purpose of the above method
 61:         if (destinationType == typeof(string) && value is ApplicationVersion)
 62:         {
 63:             var version = (ApplicationVersion)value;
 64:             return string.Format("{0}.{1}.{2}.{3}", version.Major, 
 65:                 version.Minor, version.Build, version.Private);
 66:         }
 67:         return base.ConvertTo(context, culture, value, destinationType);
 68:     }
 69: }

Finally, we’ll just create our Version property:

  1: [TypeConverter(typeof(ApplicationVersionConverter))]
  2: [Category("Custom properties"), DefaultValue("0.0.0.0"), Description("App version")]
  3: public ApplicationVersion Version { get; set; }

Here’s what we’ll get:

So, it’s possible to create properties and events that are fully design-time compatible. It might take a little work, but it’s definitely worth it, specially for people that create custom controls and plan to share or sell them. Hope you enjoyed the articles.