How to use the same generic method for validation of different types

How to use the same generic method for validation of different types

what is generics in java with simple example
java generic return type method example
java generic method parameter
java generics multiple types
java generics ? extends
t in java example
java generics tutorial
a benefit of using generics

I am having an interface IValidator which has a generic method Validate and is intended to validate different objects across the application. For now I am validating User's profile and Login credentials. The problem is, when I try to validate profile or Login class, it always calls the method for the profile even when I try to validate Login details. Here's the code:

IValidator

 public interface IValidator
{
    List<Error> Validate<T>(T request);
}

UserProfileValidator

 public class UserProfileValidator : IValidator 
{
    public List<Error> Validate<T>(T request)
    {
       //Code for profile validation
    }
}

UserLoginValidator

 public class UserLoginValidator: IValidator 
{
    public List<Error> Validate<T>(T request)
    {
       //Code for login validation
    }
}

UserService

   private readonly IValidator _validator; 

   public UserService(IValidator validator)
    {
        _validator = validator;
    }


 public async Task<Response> Login(UserDetail userDetail)
 {
     //this is supposed to validate login details, but validates profile instead
        var errors = _validator.Validate(userDetail); 
 }

public async Task<Response> UpdateProfile(Profile profile)
 {
        var errors = _validator.Validate(profile);
 }

Please guide. Thanks


I'm posting this though it may not be the solution to OP's problem.

Based on what you said you are using AutoFac.

Service:

builder.RegisterType<UserService>().As<IUserService>();

Validators:

builder.RegisterAssemblyTypes(typeof(DependencyBuilder).Assembly).Where(t => t.Name.EndsWith("Validator")).AsImplementedInterfaces().InstancePerLifetimeScope(); 

Looking at how you register your UserService you are not supplying a specific IValidator parameter to its constructor which I think is the reason why AutoFac keeps using the UserProfileValidator. Logically speaking how will UserService know what implementation of IValidator to use on run-time?

I often use the following to specify parameters to my constructors.

builder
    .Register(r => new UserService(r.Resolve<IValidator>()))
    .As<IUserService>()
    .InstancePerRequest();

But the problem with this is if the DI will resolve for the IValidator it is still not specific.

I would suggest redesigning your code since I don't think your current design allows the UserService to use both UserProfileValidator and UserLoginValidator.

Probably assigning the IValidator per view model would be a better approach so that each view model has their own implementation of IValidator then you could do something like var errors = viewModel.Validate();.

Generics in Java, How do you create a generic and generic method in Java? In the above generic method example, we have taken the same type parameter name which is used by generic class. In the main method, we have passed the <int> type argument in the Helper class. In the method, we have passed the <string> argument. Generic Overloaded Methods. C# allows you to define generic overloaded methods with many type parameters.


You should change your interface to be:

public interface IValidator<T>
{
    List<Error> Validate(T request);
}

Generic Methods (The Java™ Tutorials > Learning the Java , programming is a style of computer programming in which algorithms are written in terms of types to-be-specified-later that are then instantiated when needed for specific types provided as parameters. Generic Methods (C# Programming Guide) A generic method is a method that is declared with type parameters, as follows: The following code example shows one way to call the method by using int for the type argument: You can also omit the type argument and the compiler will infer it.


You must be using some dependency injection registration with the default DI container or Autofac. Please provide details of how you're doing so.

Your interface is not generic, which means that your dependency injection container is registering several implementations for the same interface and when you inject it it is taking the last implementation.

Change the interface to

public interface IValidator<T>
{
    List<Error> Validate(T request);
}

and inject a service IValidator<UserDetail> and another IValidator<Profile> so in essence there are different validators that use the same interface.

Using generics is ok when the implementation is generic, but in your case each validator is different therefore the DI needs to know exactly which one to use.

In autofac you should have something like

builder.RegisterType<UserLoginValidator>().As<IValidator<UserDetails>>();
builder.RegisterType<ProfileValidator>().As<IValidator<Profile>>();

Generic Classes | Tour of Scala, Some validation constraint can be applied to several different types. class is a good place to cover topics which are the same in all possible implementations: the declaration of a served constraint annotation using generic from a validated type to LocalDate which output is verified in the isValid() method. Analytical method validation, thinking about the maximum relevant processes for checking the best parameters of analytical methods, using numerous relevant overall performance indicators inclusive of selectivity, specificity, accuracy, precision, linearity, range, limit of detection (LOD), limit of quantification (LOQ), ruggedness, and robustness are severely discussed in an effort to prevent their misguided utilization and ensure scientific correctness and consistency among publications.


Thanks all of you for the help, it did help me to solve this problem. I used Autofac's keyed services to Register both the validators as IValidator, then resolved by index as needed.

see this: https://autofaccn.readthedocs.io/en/latest/advanced/keyed-services.html

Coding Concepts - Generics, Metadata Validation Error Codes and Messages (continued) HRESULT Error Message 0x80131B24 Error: Illegal use of type 'void' in signature. 0x80131B2D Error: GenericParam is a method type parameter and must be non-​variant, not co- or is non-contiguous with preceding constraints for same owner​, token=0xffffffff. Cross-validation is a comparison of validation parameters when two or more bioanalytical methods are used to generate data within the same study or across different studies. It can be used as a means of determining inter-method equivalency or assessing inter-laboratory execution of the same method.


Custom validation annotation for multiple types, If F is generic and M includes a type argument list, F is a candidate when • F has the same number of method type parameters as were method type parameters, all constructed types in the parameter list of F satisfy The best method of the set of candidate methods is identified using the overload resolution rules of §7.4.3. Cross-parameter constraints can be considered as the method validation equivalent to class-level constraints. We could use both to implement validation based on several properties. We could use both to implement validation based on several properties.


.NET IL Assembler, So, using Generics is all about abstracting the type from a method or a to their data types (predefined/user-defined) thereby reusing the same  The harmonization team has the following definition of cross validation: Cross validation is a comparison of data from at least two different analytical methods (reference method and test method) or from the same method used by at least two different laboratories (reference site and test site) within the same study.


The C# Programming Language, Solid Oral Dosage Forms, Second Edition Leon Shargel, Isadore Kanfer The screening dissolution test method is not necessarily the same as the method used for formulation development needs to be discriminative for different formulations purity tests can often save method development and method validation time. Information about generic types is obtained in the same way as information about other types: by examining a Type object that represents the generic type. The principle difference is that a generic type has a list of Type objects representing its generic type parameters. The first procedure in this section examines generic types.