I'm trying to write a generic method parameter validation functionality that can be chained (fluent interface) to attach more and more validations/checks like:
public void SomeMethod(User user, string description)
{
ParameterHelper
.Create(() => user)
.RejectNull();
ParameterHelper
.Create(() => description)
.RejectNull()
.RejectEmptyString();
// now this would be luxurious
ParameterHelper
.Create(() => new { user = user, desc = description })
.RejectNull(o => o.user)
.RejectNull(o => o.desc)
.RejectEmptyString(o => o.desc);
}
I would like to use this helper class to test method parameters for certain values before using them (most of the time null
will be tested).
Current state of affairs
I first started writing static helper class without the Create()
method like:
public static class ParameterHelper
{
public static void RejectNull(Expression<Func<T>> expr)
{
if (expr.Compile()().Equals(default(T)))
{
MemberExpression param = (MemberExpression)expr.Body;
throw new ArgumentNullException(param.Member.Name);
}
}
}
But this doesn't allow chaining. That's why I created the Create()
method that would return something that can be used by chained extension methods.
The problem
- I would like to avoid multiple
Compile()
calls, so basically myCreate()
method should returnFunc<T>
and reject methods should be extension methods ofFunc<T>
. - If my
Create()
does returnFunc<T>
I don't get the chance to read parameter names that should be supplied to various exceptions (usingMemberExpression
). - If I return
Expression<Func<T>>
instead I will have to callCompile()
in eachReject
extension method.
Questions
- Is there a C# library that already does this kind of chaining?
- If not, what do you suggest how this should be done? Any examples from the web would be warmly welcome.
Additional note
I should point out that complex/long validation invocation code is not an option here, because my current validation is done like:
if (user == null)
{
throw new ArgumentNullException("user");
}
or
if (string.IsNullOrEmpty(description))
{
throw new ArgumentNullException("description");
}
Which has two major drawbacks:
- I repeat the same lines of code over and over
- it uses magic strings
So validation should be done with a one liner per check as described above in the desired scenario.
There is a simple way to implement such a fluent interface. Your 'ParameterHelper.Create' method should return an instance of some class (this class is named
Requirements
below). This instance should hold the expression which was passed toCreate
. Also this class should haveRequire...
instance methods which will validate expression and returnthis
.Requirements
class can be a private class insideParameterHelper
. I would also introduce an interface for this requirements chain (this interface is namedIRequirements
below. Sample:This approach will allow you implementing your
luxurious
solution - you just need to add a corresponding parameters toReject...
methods. Also you will probably need to makeIRequirements
interface generic.