Another way to provide a caller with optional arguments on a call is to use overloads. These can get messy when there are too many, but if you just have a few you can write them once using Extensions.
For a service, it is usual to create an interface class to define the API between the service and its consumers.
This allows you to have many implementers of the same interface which can be swapped out to do the work.. and gives you an interface to mock when you are testing the consumers in isolation.
So, say I have created a service interface, for which there will be many implementations.
One of the methods on this service is to write to a file. I want to allow the caller to optionally call the method without an encoding, in which case I will use the default encoding.
This gives me two methods
public void Write(string content) { ... }
public void Write(string content, Encoding encoding) { ... }So I could go ahead an create an interface which requires the two methods for an implementation, but ...
I would always expect the first to call the second in the same way, passing a default for the encoding parameter.
And I am allowing the implementer to decide the default encoding, which potentially means a different implementation may have a different default. This may be desired, but generally I think it would break the Substitution Principle.
It would be better to have only one method here and supply the second method in another way.
So here is my interface
public interface IWriterService
{
void Write(string content, Encoding encoding);
}This asks the implementer to create one method which is given all the arguments it need to complete the job.
You could supply the second method by using a base class, this is valid, but is another constraint on the implementer as they would not be able to use there own base class.
Instead I supply the second method using an extension, passing the encoding argument from within the method, effectively making the encoding parameter optional.
public static class WriterServiceExtensions
{
public static void Write(this IWriterService writer, string content)
{
writer.Write(content, Encoding.Default);
}
}Place this in the same namespace as the interface, that way the method is already in scope if you are calling against the interface.
Here's a test to confirm all is well ...
void extension_calls_service()
{
const string content = "Hello";
var moq = new Mock<IWriterService>();
moq
.Setup(x => x.Write(content, Encoding.Default))
.Verifiable();
// act
moq.Object.Write(content);
// assert
moq.Verify();
}Now I can go and code my implementations - or get someone else to - and I know that the second method will be the same and available for all.
Code
Available on GitHub as a VS2010 solution
References
http://msdn.microsoft.com/en-us/library/bb383977(v=vs.100).aspx

