I’m using .NET 3.5. We have some complex third-party classes which are automatically generated and out of my control, but which we must work with for testing purposes. I see my team doing a lot of deeply-nested property getting/setting in our test code, and it’s getting pretty cumbersome.
To remedy the problem, I’d like to make a fluent interface for setting properties on the various objects in the hierarchical tree. There are a large number of properties and classes in this third-party library, and it would be too tedious to map everything manually.
My initial thought was to just use object initializers. Red, Blue, and Green are properties, and Mix() is a method that sets a fourth property Color to the closest RGB-safe color with that mixed color. Paints must be homogenized with Stir() before they can be used.
Bucket b = new Bucket() {
Paint = new Paint() {
Red = 0.4;
Blue = 0.2;
Green = 0.1;
}
};
That works to initialize the Paint, but I need to chain Mix() and other methods to it. Next attempt:
Create<Bucket>(Create<Paint>()
.SetRed(0.4)
.SetBlue(0.2)
.SetGreen(0.1)
.Mix().Stir()
)
But that doesn’t scale well, because I’d have to define a method for each property I want to set, and there are hundreds of different properties in all the classes. Also, C# doesn’t have a way to dynamically define methods prior to C# 4, so I don’t think I can hook into things to do this automatically in some way.
Third attempt:
Create<Bucket>(Create<Paint>().Set(p => {
p.Red = 0.4;
p.Blue = 0.2;
p.Green = 0.1;
}).Mix().Stir()
)
That doesn’t look too bad, and seems like it’d be feasible. Is this an advisable approach? Is it possible to write a Set method that works this way? Or should I be pursuing an alternate strategy?
Does this work?
Assuming
Mix()andStir()are defined to return aPaintobject.To call methods that return
void, you can use an extension method that will allow you to perform additional initialization on the object you pass in:Which could be used similar to Set() as described: