Home > General > Castle DictionaryAdapter – Using TypeConverter to map different types

Castle DictionaryAdapter – Using TypeConverter to map different types

I’ve posted about the DictionaryAdapter a few times in the past (here and here). There are scenarios when we want to map more than just simple types to strings. For example, we have an interface IPerson with the property Birthday representing the date in ticks.

public interface IPerson
{
    string Name { get; set; }
    int Age { get; set; }
    long Birthday { get; set; }
}

If we attempt to map a DateTime to the property Birthday, an InvalidCastException will be thrown when we access the Birthday property.

var dictionary = new Dictionary<string, object>
{ 
    { "Name", "John Doe" },
    { "Age", 30 },
    { "Birthday", DateTime.Now },
};

IPerson person = new DictionaryAdapterFactory()
	.GetAdapter<IPerson>(dictionary);

Console.WriteLine(person.Birthday);

Fortunately, the DictionaryAdapter allows us to use attributes to define how properties should be mapped by creating a class that inherits from System.ComponentModel.TypeConverter.

public class DateTimeToTicks : TypeConverter
{
	public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
	{
		if (sourceType == typeof(DateTime))
			return true;
		
		return base.CanConvertFrom(context, sourceType);
	}

	public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
	{
		return ((DateTime)value).Ticks;
	}
}

We can decorate the Birthday property with the TypeConverter attribute and specify that we want to use our new type converter.

[TypeConverter(typeof(DateTimeToTicks))]
long Birthday { get; set; }

The previous example is a bit contrived. However, I have run into issues when trying to use the DictionaryAdapter with a result set from a database that contains NULLs. Here we’ve updated the IPerson interface with a Nullable<int>.

public interface  IPerson
{
    string Name { get; set; }
    int? Age { get; set; }
}

The following code will throw an InvalidCastException on line 17 after mapping the results from a SQL query:

using (var conn = new SqlConnection(connStr))
using (var cmd = new SqlCommand("select 'John Doe' as [Name], NULL as [Age]", conn))
{
    conn.Open();

    using (SqlDataReader dr = cmd.ExecuteReader())
    {
        while (dr.Read())
        {
            var dictionary = Enumerable
                .Range(0, dr.FieldCount)
                .ToDictionary(dr.GetName, dr.GetValue);

            IPerson person = new DictionaryAdapterFactory()
                .GetAdapter<IPerson>(dictionary);

            Console.WriteLine(person.Age);
        }
    }
}    

We can create another TypeConverter to check for DBNull and returns null if found.

public class DBNullable : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        if (sourceType == DBNull.Value.GetType())
            return true;

        return base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (DBNull.Value.Equals(value))
            return null;

        return base.ConvertFrom(context, culture, value);
    }
}

Again, we can decorate the Age property with our new type converter.

[TypeConverter(typeof(DBNullable))]
int? Age { get; set; }
  1. March 8, 2015 at 4:25 am

    Hi admin, i found this post on 18 spot in google’s
    search results. I’m sure that your low rankings are caused by hi
    bounce rate. This is very important ranking factor. One of the biggest reason for high bounce rate
    is due to visitors hitting the back button. The higher
    your bounce rate the further down the search results
    your posts and pages will end up, so having reasonably low
    bounce rate is important for improving your rankings naturally.
    There is very handy wp plugin which can help you.
    Just search in google for:
    Seyiny’s Bounce Plugin

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: