Call several methods with the same output and another input to the loop

I have several methods with different input parameters and the same outputs.

I call Method1 with the input type of the number and then check its result, if the result is valid, the next method is called (this time with the input type of the type), etc.

In this example, I have three methods, but if I have 10 methods or 20 methods with different inputs and the same outputs, I have to write redundant code, how can I prevent these redundant codes?

This is an example of methods:

public ValidationResult Method1(int number, string family) { var validationResult = new validationResult(); if(number > 10 || family="akbari") { validationResult.Errors.Add(new ValidationFailure("", "Invalid Number")); } return validationResult; } public ValidationResult Method1(string name) { var validationResult = new validationResult(); if(name.Length > 20) { validationResult.Errors.Add(new ValidationFailure("", "Invalid name")); } return validationResult; } public ValidationResult Method1(double average, string family) { var validationResult = new validationResult(); if(average < 14) { validationResult.Errors.Add(new ValidationFailure("", "Invalid average")); } return validationResult; } 

And I call these methods as follows:

 var validationResult = Method1(20, "test"); if (!validationResult.IsValid) { return validationResult.FirstError(); } validationResult = Method2("Samsung"); if (!validationResult.IsValid) { return validationResult.FirstError(); } validationResult = Method3(15.5); if (!validationResult.IsValid) { return validationResult.FirstError(); } 
+5
source share
4 answers

(also check out the alternative solution below!)

 var valMethods = new List<Func<ValidationResult>> { ()=>Method1(number,family), ()=>Method2(name), // ... }; foeach(var valMethod in valMethods) { var valResult = valMethod(); if (!valResult.IsValid) { return valResult.Errors.First(); } } 

This happens, however, with some performance degradation for delegates, and since you need parameters, it's hard to put it outside, for example. in the method returning delegates.

Alternatively, you can create a batch of values ​​as a parameter (maybe your calling class with the appropriate interface), which is the same for all methods, and each method selects what it needs (which, in turn, makes the verification methods less clear )

Another alternative would be to simply return the bool values ​​and save the verification details in separate objects, perhaps implement extension methods for verification (also check the response of Myleo predicates):

 internal static class ValidationMethods { public static bool CheckIsValid1(this IList<ValidationResult> valResults, int number, string family) { var validationResult = new validationResult(); if(number > 10 || family="akbari") { validationResult.Errors.Add(new ValidationFailure("", "Invalid Number")); } valResults.Add(validationResult); return validationResult.IsValid; } public static bool CheckIsValid2(this IList<ValidationResult> valResults, string name) { // next check ... } } 

then, when checking the code:

 var valResults = new List<ValidationResult>(); if (!valResults.CheckIsValid1(number, family) || !valResults.CheckIsValid2(name) || // more checks... will stop if one fails ) { return valResults.Last().Errors.First(); } 

This way you do not have to talk to delegates. The checks stop when the first failure (or the status check stops at the first success, IsValid is denied here). And your valResults still contain validation data.

From your code, it might also just be easy to use exceptions. Such an exception check may be required if errors occur frequently and exceptions kill performace, but if errors are exceptional, then feel free to use the exception!

+3
source

maybe with a predicate ?

you can do something like

  public ValidationResult Method1(string name) { return Validate(name, (param) => param.Length > 20, "Invalid name"); } public ValidationResult Method1(double average) { return Validate(average, (param) => param < 14, "Invalid average"); } private ValidationResult Validate<T>(T param, Func<T, bool> predicate, string message) { var validationResult = new validationResult(); if (predicate(param)) { validationResult.Errors.Add(new ValidationFailure("", message)); } return validationResult; } 

If you have a lot of options. This is not the best way, but:

  public ValidationResult Method1(int number, string family) { return Validate(number > 10 || family == "akbari", "Invalid Number"); } public ValidationResult Method1(string name) { return Validate(name.Length > 20, "Invalid name"); } public ValidationResult Method1(double average) { return Validate(average < 14, "Invalid average"); } public ValidationResult Validate(bool predicate, string message) { var validationResult = new validationResult(); if (predicate) { validationResult.Errors.Add(new ValidationFailure("", message)); } return validationResult; } 
+3
source

I assume that one problem is the method signature, some accept int and others accept string..etc; How to create a new type for yourself, say, InputParam:

 public class InputParam { private int fieldOne; private string fieldTwo; ... GetFieldOne(); GetFieldTwo(); ... } 

Then you can have as many methods as you need, Method1 to 20. Of course, each method will be responsible for collecting only the fields that it needs from an instance of InputParam.

Now all your methods use the same signature, so you can have an array of methods and a loop against it.

+2
source

you can use a keyword like

  static void Main(string[] args) { Console.WriteLine(@" Method1(1)-> return {0}; Method1('1')-> return {1}; Method1(0.1)->-> return {2};" , Method1(1), Method1("1"), Method1(0.1)); Console.WriteLine(@" AvgMethod()-> return {0}; AvgMethod(1)-> return {1}; AvgMethod('1')-> return {2}; AvgMethod(0.1)-> return {3};" , AvgMethod() , AvgMethod(1) , AvgMethod("1") , AvgMethod(0.1)); Console.ReadLine(); } public static string Method1(int number) { return "int"; } public static string Method1(string name) { return "string"; } public static string Method1(double average) { return "double"; } public static string AvgMethod(object _argument = null) { if (_argument is int) return "int"; if (_argument is string) return "string"; if (_argument is double) return "double"; return "..."; } 
+1
source

Source: https://habr.com/ru/post/1261103/


All Articles