c# - Dependency Injection with inheritance -


i'm using pipeline build mediatr. i'm adding simple behavior aimed @ validating queries , commands:

public class validationbehavior<trequest, tresponse> : ipipelinebehavior<trequest, tresponse>     trequest : irequest<result>     tresponse : result {     private readonly ienumerable<ivalidator<trequest>> _validators;      public validationbehavior(ienumerable<ivalidator<trequest>> validators)     {         _validators = validators ?? enumerable.empty<ivalidator<trequest>>();     }      public async task<tresponse> handle(trequest request, requesthandlerdelegate<tresponse> next)     {       (...)     } } 

currently of queries inherits paginatedquery.

public abstract class paginatedquery : iquery {     public int offset { get; set; } = 0;     public int limit { get; set; } = 25; } 

example:

public class getcountriesquery : paginatedquery {     public getcountriesquery(paginatedinput input)     {         limit = input.limit;         offset = input.offset;     } } 

to make sure users don't send invalid offset/limit, have built following validator:

public class paginatedqueryvalidator : abstractvalidator<paginatedquery> {     public paginatedqueryvalidator()     {         rulefor(p => p.offset)             .greaterthanorequalto(0)             .withmessage("offset must greater or equal 0");         rulefor(p => p.limit)             .greaterthan(0)             .withmessage("limit must greater 0");     } } 

unfortunately validator not injected validationbehavior though trequest inheriting paginatedquery.

in end, need inject validators current trequest , mother classes (ie: paginatedquery).

is achievable?

note: inject validators, scan types implementing ivalidator<> (using scrutor)

        services.scan(x =>             x.fromassembliesof(typeof(startup))                 .addclasses(c =>                     c.assignabletoany(typeof(ivalidator<>)))                 .asimplementedinterfaces()         ); 

edit: forgot mention i'm using autofac

when autofac resolves validationbehavior<getcountriesquery, getcountriesresponse> expect resolve ivalidator<getcountriesquery> whereas ivalidator<paginatedquery> registered , ivalidator<paginatedquery> not assignable ivalidator<getcountriesquery>

you can try using following c# statement

ivalidator<getcountriesquery> = (ivalidator<paginatedquery>)null; 

the c# compiler give error message

error cs0266 : cannot implicitly convert type ivalidator<paginatedquery> ivalidator<getcountriesquery>. explicit conversion exists (are missing cast?)

in order make work, c#4 introduces covariance , contravariance generic type parameter. allows cast ivalidator<base> ivalidator<derived> or opposite. see covariance , contravariance on msdn more information.

in case need contravariance can declared using in keyword

public interface ivalidator<in trequest> { } 

in order make autofac works contravariant have register contravariantregistrationsource registration source :

builder.registersource(new contravariantregistrationsource()); 

Comments

Popular posts from this blog

angular - Ionic slides - dynamically add slides before and after -

minify - Minimizing css files -

Add a dynamic header in angular 2 http provider -