views:

95

answers:

4

I have a fluent validation API that throws an exception when a supplied boolean result is false. This works fine.

I'd like to improve upon this by, instead of throwing an exception, providing some functionality to execute if the result is false, and then forcing the calling method to return. Example, the supplied functionality might new up a response, initialise it appropriately and return it.

Is doing this even possible? (I suspect not).

Work around seems to be something like initializing an out param (the response), and returning that from the calling method.

Desired:

Ensure.That(request.IsValid(), () => new Response { Errors = request.Errors }); //I want lambda to force containing method reeturn

As implemented:

Response response;
            Ensure.That(request.IsValid(), r => new Response{Errors = request.Errors}, out response);
            if (response.IsNotNull()) return response;
+4  A: 

The calling method has to know to do it, basically. How you signal that is up to you - a return value, an out parameter etc - but you can't force it from the delegate itself other than with an exception (which could still be caught, of course).

Jon Skeet
+1  A: 

There is no way, in any language that I know of, to control a caller's logical execution path. Even throwing an exception does not influence a caller because the caller can simply trap it.

Things like this are done with macros in C++, but C# provides nothing like macros.

Tergiver
Ruby: http://strugglingwithruby.blogspot.com/2009/02/ruby-proc.html
recursive
I was not familier with Ruby, but I am familier with methods as 1st-class citizens and while you can return methods which might get called by the caller, the logical flow of the caller is not changed. The caller might run or not run additional code, but it is still the only one responsible for terminating itself.
Tergiver
+1  A: 

As Skeet said, you have to tell your method how you want it return your data. One example (knowing nothing about your specific app) could be something like this:

public void CheckValidationRules(ValidationRuleSet rules, object obj)
{
  //Your validation code here.
  while(!SomeValue) // currently throws, but we're, instead calling a new method
    FixThisProblem(ValidationError, obj, out SomeValue);
}

private void FixThisProblem(ValidationError error, object objInError, out bool someValue)
{
  //Your Code to fix the problem, then check that rule again
  if(!someValue) // recursively try to fix?  throw an exception?  whatever
  someValue = true;
}

Then your faulted method can handle this gracefully, and then continue with its operation. Note that I have the call to the FixThisProblem() method in a while loop so that you can recursively fix if there could be multiple problems that all return the same error.

AllenG
+1  A: 

Not directly - what you can do is throw an exception and catch it in the calling method. The calling method can expect that particular type of exception and return on the finally.

A better solution would just to have an out paramater or return value and return if that checks out.

What you want is to have one method inject code into another for a specific instance - methods aren't generated for objects for every object instantiated- just what's needed like member values. What you are really asking would open up a can of worms that would raise hundreds of questions - scope, private/public, etc. I don't think it's possible - I really hope it isn't.

diadem