I have base generic interface
public interface ICRUDStore<Model> where Model : class
{
Task<IEnumerable<Model>> FindAsync();
Task<Model> FindAsync(int id);
Task UpdateAsync(int id, Model updatedRecord);
Task DeleteAsync(int id);
Task CreateAsync(Model record);
}
and it's child interface
public interface ICourseStore : ICRUDStore<Course>
{
Task<IEnumerable<Course>> FindByMenuIdAsync(int menuId);
}
where Course
is basic model class.
I'm implementig this repository with PgCourseStore : PgStore<Course>, ICourseStore
where PgStore<Course>
is a base class for working with Postgres.
I have abstract base controller class
public abstract class BaseController<Model, Store> : ApiController
where Model : class
where Store : ICRUDStore<Model>
protected readonly Store store;
with basic CRUD methods and its child controller with special queries CoursesController : BaseController<Course, ICourseStore>
where I need store
variable to be ICourseStore
to call special queries.
So when i'm trying to bind PgCourseStore
with ICourseStore
with different IoC containers (like DryIOC, Autofac) everything works fine when FindAsync methods are called from my base controller. But when i'm trying to call Update, Delete or Create methods i'm getting Microsoft.CSharp.RuntimeBinder.RuntimeBinderException whith message that ICourseStore doesn't have definition for CreateAsync method.
Yes, I can store store
like ICRUDStore type and casting it when I need, but may be there is more beautiful solution?
UPD: BaseController
looks like
public abstract class BaseController<Model, Store> : ApiController
where Model : class
where Store : ICRUDStore<Model>
{
protected abstract Model Parse(dynamic model);
protected readonly Store store;
public BaseController(ICRUDStore<Model> store)
{
this.store = store;
}
public virtual async Task<HttpResponseMessage> Get()
{
var records = await store.FindAsync();
return Request.CreateResponse(HttpStatusCode.OK, records);
}
public virtual async Task<HttpResponseMessage> Post(dynamic value)
{
var model = Parse(value);
await store.CreateAsync(model);
return Request.CreateResponse(HttpStatusCode.Created);
}
}
And CourseController
public class CoursesController : BaseController<Course, ICourseStore>
{
public CoursesController(ICourseStore store) : base(store) { }
}
So I don't see any meaningfull difference between using of Create* and Find* methods. Both of these methods are defined in my base PgStore<Model>
class (not in PgCourseStore) while I'm binding just ICourseStore and PgCourseStore.
It was the dynamic
type that caused runtime binding error. Changing to object
could help you:
public virtual async Task<HttpResponseMessage> Post(object value)
{
var model = Parse(value);
await store.CreateAsync(model);
return Request.CreateResponse(HttpStatusCode.Created);
}