i playing around test project. trying implement cqs pattern , getting close wrapping initial tests. have run issue trying resolve iqueryvalidtor<>
, iqueryhandler<,>
classes. method resolves them alright, when try access interface methods implemented in concrete class,
the best overloaded method match 'myprojectsnamespace.getsitevalidator.validate(myprojectsnamespace.queries.getsite)' has invalid arguments.
i basing code on this answer found. appears lining during design time, run time different story.
i including of interfaces, implementations, , unit tests working on issue. first unit test working. last 2 trying use resolved classes. using autofac dependency injection.
public interface iquery<tresult> { } public class getsite : iquery<site> { public guid id { get; set; } } public interface ivalidator<t> { task<list<validationresult>> validate(t command); } public class getsitevalidator : ivalidator<getsite> { public async task<list<validationresult>> validate(getsite command) { list<validationresult> results = new list<validationresult>(); if(command == null) { throw new argumentnullexception(nameof(command)); } if(command.id == guid.empty) { results.add(new validationresult() { fieldname = "id", message = "is empty" }); } return results; } } public interface iqueryhandler<in tquery, tresult> tquery : iquery<tresult> { task<tresult> handle(tquery query); } public class getsitehandler : iqueryhandler<getsite, site> { public task<site> handle(getsite query) { throw new notimplementedexception(); } }
the code above of interfaces , concrete classes used in problem. code below dispatcher class having issue.
public class querydispatcher : iquerydispatcher { private readonly icomponentcontext _context; public querydispatcher(icomponentcontext context) { _context = context; } public async task<tresult> dispatch<tresult>(iquery<tresult> query) { if (query == null) { throw new argumentnullexception(nameof(query), "query cannot null"); } // use dynamic datatype because tresult not known @ compile time var validatortype = typeof(ivalidator<>).makegenerictype(query.gettype()); dynamic validator = _context.resolve(validatortype); var handlertype = typeof(iqueryhandler<,>).makegenerictype(query.gettype(), typeof(tresult)); dynamic handler = _context.resolve(handlertype); list<validationresult> errors = await validator.validate(query); if(errors.count == 0) { return await handler.handle(query); } else { // raise failed validation event throw new applicationexception("not implemented"); } } }
you passing iquery<tresult> query
object validate(getsite)
method - method requires getsite
type.
even though getsite
implements iquery<tresult>
, compiler can't guarantee iquery<tresult> query
object of type getsite
- other type implementing iquery<tresult>
cast not possible.
Comments
Post a Comment