The goal: create an extension method that will make it easy to create FormCollection objects. The method is a helper for unit testing ASP.NET MVC code.
public static FormCollection ToFormCollection(this object data) { var namesAndValues = data.GetType() .GetProperties() .WhereValueIsNotDefaultValue(data) .ToNameValueCollection(data); return new FormCollection(namesAndValues); }
The extension method itself relies on a couple private extension methods:
static IEnumerable<PropertyInfo> WhereValueIsNotDefaultValue( this IEnumerable<PropertyInfo> properties, object source) { foreach(var p in properties) { var value = p.GetValue(source, null); if(value != (p.PropertyType.IsValueType ? Activator.CreateInstance(p.PropertyType) : null)) { yield return p; } } } static NameValueCollection ToNameValueCollection( this IEnumerable<PropertyInfo> properties, object source) { return properties.Aggregate( new NameValueCollection(), (nvc,pi) => { var value = pi.GetValue(source, null); nvc.Add(pi.Name, value.ToString()); return nvc; }); }
The code mostly works. This test passes:
public void should_copy_property_values() { var expectedName = "Scott"; var expectedHireDate = new DateTime(2010, 1, 1); var data = new Employee { Name = expectedName, HireDate = expectedHireDate }.ToFormCollection(); Assert.IsTrue(data["Name"] == expectedName); Assert.IsTrue(data["HireDate"] == expectedHireDate.ToString()); }
However, the helper should not put entries in the FormCollection for properties holding a default value, and this test fails:
public void should_not_copy_default_values() { var data = new Employee { Name = "", HireDate = DateTime.Now }.ToFormCollection(); Assert.IsNull(data["Tags"]); Assert.IsNull(data["Id"]); }
Employee is defined as:
public class Employee { public int Id { get; set; } public string Name { get; set; } public DateTime HireDate { get; set; } public string Tags { get; set; } }
Hint: the first assert passes – it’s the assert on data[“Id”] that fails.