Dynamic object activation, the cool way


After working with ASP.NET MVC for some time I learned to love and appreciate the little things in the framework that are done really well. One of those, that sticks out in my view, is the way that the HTML attributes are passed to view items.

Html.TextBox("UserName", Model.UserName, new {@readonly = "readonly"})

I personally think that the new {@readonly = “readonly”} syntax has something interesting. The potential usage of this are quite mind-blowing . I intend to create a generic validator activator in the near future, for now I just implemented a simple test instance initialization.

In valy a validator is initialized by providing a validation initialization contexts. One of the key components of this is a dictionary which is then used to setup the validator state (more about this in a later post). What I wanted was a streamline syntax to initialize a validator for unit testing. The original implementation of this was something like the following:

var validator = new StringInRange(new Configuration.Confiuration{Message = "Error message", ThrowException = true, Parameters = new { { "MinValue", 1 } }});

Not really that “sexy”, and I wanted to make it sexy. So I turned to our old friend reflector and took a closer look at how it is done in the ASP.NET MVC framework. What came out is the following.

[Test]
public void Validate_PassInRangeString_ValidationPasses()
{
  var validator = TestHelper.Create<string, InRange>(ERROR_MESSAGE, false, new { @MinLenght = 3, @MaxLenght = 7 });

  var results = validator.Validate(IN_RANGE_STRING);

  results.Passed();
}

This gives us a nice little unit test that is neatly separated into a setup, action, assert sections. Or in the more modern therms: Given, when, then.

And I think that this is quite simple and straight forward. There are some problems with this implementation but still I think that it is a great start.

To come now to the interesting side of the implementation. Here is the implementation of the Create method.

public static IValidator<T> Create<T, TValidator>(string message, bool throwException, object parameters)
{
  var parameterDictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);

  if (parameters != null)
  {
    foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(parameters))
    {
      object value = descriptor.GetValue(parameters);
      parameterDictionary.Add(descriptor.Name, value);
    }
  }

  var configuration = new Configuration.Confiuration
  {Message = message, ThrowException = throwException, Parameters = parameterDictionary};

  return (IValidator<T>)Activator.CreateInstance(typeof(TValidator), configuration);
}

If you are wandering what happens behind the scenes let me explain.

Behind the scenes a dynamic object is created with the properties MaxLenght and MinLenght. When the Create method gets this dynamic object all I does is to iterate through all the public properties and create a Dictionary where the property names are the keys and the property values become the values of the dictionary. This dictionary is then passed to the validator constructor and all is well again.

I intend to make this Object -> Dictionary step unnecessary by providing a constructor overlay that will handle this dynamic object. But this is still in the future.

What has to be mentions is that there is a problem with this. At least I have a problem. And that is when I want to set a property of the type System.Type. The problem is that the property does not get set to type System.Type but to System.RuntimeType. But this is a minor setback that should be solved in the near future.

All in all this is a great way to make unit tests simpler.

Advertisements

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