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
Post a Comment