AutoFixture/AutoFixture — pull request #319 by ecampidoglio (2014-10-15 21:36:55+00:00)
Title: The Matching DSL

Built on top of the `IRequestSpecification` abstraction, this customization API makes it possible to associate specimen builders with different kinds of requests.

### Usage

Here's an example of how it can be used:

```csharp
fixture.Customize(c => c
.Without(s => s.AProperty)
.Match()
.ByBaseType()
.Or.ByInterfaces()
.Or.ByProperty("TheFoo"));
```

This effectually means:

> Create instances of `Foo` by omitting the `AProperty` property for every request for a type that is either a **direct base** of `Foo`, one of its **implemented interfaces** or for a **property named** `"TheFoo"` whose type is compatible (i.e. contravariant) to `Foo`.

A couple of things to point out:

- `Match()` is implemented as an extension method to `IPostprocessComposer`.
- The matching behavior is independent of the specimen builder used to satisfy the requests.

### Background

The idea behind the Matching DSL is to bring a simple and fairly common scenario like matching anonymous values based on different criteria up to a "user friendly" high level API, while in the past it used to require interaction with the lower level constructs.

Here's a concrete example taken from @ploeh's [post about building conventions in AutoFixture](http://blog.ploeh.dk/2010/10/19/Convention-basedCustomizationswithAutoFixture/).

In order to assign a valid currency code to all string parameters named "*currencyCode*", one would have to implement a custom `ISpecimenBuilder` and check for the right kind of requests:

```csharp
public class CurrencyCodeSpecimenBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var pi = request as ParameterInfo;

if (pi == null)
{
return new NoSpecimen(request);
}

if (pi.ParameterType != typeof(string)
|| pi.Name != "currencyCode")
{
return new NoSpecimen(request);
}

return "DKK";
}
}
```

Even if we're all very familiar with the concepts mentioned in that class (*specimen*, *request*, *specimen context*, *no specimen*) I'm pretty sure that they're completely foreign to most people who are approaching AutoFixture for the first time. And rightly so, since they belong to the realm of lower level abstractions.
In addition, this approach also requires you to deal with Reflection types directly.

Compare that with a customization that uses the Matching DSL:

```csharp
fixture.Customize(c => c
.FromFactory(() => "DKK")
.Match().ByParameter("currencyCode"));
```

I can't count how many times I've wished I could simply write these kinds of customizations without having to first make custom builders, request specifications and so on.

### Follow-ups

The XML documentation is currently missing and I'll add it once the feature is finalized.

I look forward to your comments.