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.