Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Func<T,bool>[] as a parameter list and check the result for each function

UPDATED: I am trying to write a method to do somes work and before it actually does those works it needs to go through some validations. Those validation varies based on what work it's going to do.

After some thoughts, I still want to use the same patterns with some minor changes. Now, I want to make the following code works:

SomeClass:

        public SomeResponse DoSomething<T>(params Func<T, bool>[] validations)
        {
            if(validations.All(v=>v(T))
            {
                some logic..
            }
            return SomeResponse;
        }

Usage:

       private Func<SomeRequest, bool> ValidateName = r =>
        {return !string.IsNullOrWhiteSpace(r.Name);};
       private Func<SomeRequest, bool> ValidatePhone = r =>
        {return !string.IsNullOrWhiteSpace(r.Phone);};

       var someResponse = SomeClass.DoSomething<SomeRequest>(ValidateName,ValidatePhone);

Again, the code currently doesn't work because it's giving me error on

if(validations.All(v=>v(T))

basically Type parameter is not valid here, and I couldn't find a way to pass in an actual SomeRequest object to the Func.

How should I write the code to loop through all the results return by the list of functions and make sure they are returning true, as well as keeping the flexibility of the Type parameter?

Answer:

Found a way to do that, hope this can be helpful:

Simply modify the method definition to :

SomeClass:

    public SomeResponse DoSomething<T>(T request, params Func<T, bool>[] validations)
    {
        if(validations.All(v=>v(request))
        {
            some logic..
        }
        return SomeResponse;
    }

Then use it like:

var someResponse = SomeClass.DoSomething<SomeRequest>(someRequest, ValidateName,ValidatePhone);

Please let me know if there is any other solution.

like image 950
plasmaxy Avatar asked Jan 07 '23 09:01

plasmaxy


1 Answers

You're almost there!

First note that Validations is an array of Func<Request, bool> - that is, each item in the array is a function which takes a Request as a parameter and returns a bool.

So in order to get the bool out of the Func, you need to apply it to a Request object. In C#, applying a Func to an argument looks just like calling a method. So your LINQ expression will look like this:

validations.All(f => f(request))

This will return true if and only if all of the functions in validations return true (when applied to request).

So your full if block will look like this:

// I'm just guessing what the code to make a Request object will look like
Request request = resource.GetRequest();

if (!validations.All(f => f(request)))
{
    throw new Exception("Not all of the validations checked out");
}

You haven't provided enough context for me to tell you where to get a Request object from but I'm sure you can figure it out.

like image 106
Benjamin Hodgson Avatar answered Jan 09 '23 22:01

Benjamin Hodgson