1

У меня есть базовая общий интерфейсДетский интерфейс общего интерфейса IoC bindnig в C#

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); 
} 

, и это ребенок интерфейсу

public interface ICourseStore : ICRUDStore<Course> 
{ 
    Task<IEnumerable<Course>> FindByMenuIdAsync(int menuId); 
} 

где Course является основным классом модели. Я реализую этот репозиторий с PgCourseStore : PgStore<Course>, ICourseStore, где PgStore<Course> является базовым классом для работы с Postgres.

У меня есть абстрактный базовый класс контроллера

public abstract class BaseController<Model, Store> : ApiController 
             where Model : class 
             where Store : ICRUDStore<Model> 
protected readonly Store store; 

с основными методами CRUD и его контроллер ребенка со специальными запросами CoursesController : BaseController<Course, ICourseStore>, где мне нужно store переменную быть ICourseStore вызова специальных запросов.

Так что, когда я пытаюсь связать PgCourseStore с ICourseStore с различными контейнерами IoC (например, DryIOC, Autofac), все работает отлично, когда методы FindAsync вызывают из моего базового контроллера. Но когда я пытаюсь вызвать методы «Обновить», «Удалить» или «Создать», я получаю сообщение Microsoft.CSharp.RuntimeBinder.RuntimeBinderException с сообщением о том, что у объекта ICourseStore нет определения для метода CreateAsync. Да, я могу хранить store, как тип ICRUDStore, и отбрасывать его, когда мне нужно, но может быть есть более красивое решение?

UPD:BaseController выглядит

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); 
    } 
} 

И CourseController

public class CoursesController : BaseController<Course, ICourseStore> 
{ 
    public CoursesController(ICourseStore store) : base(store) { } 
} 

Так что я не вижу никакой разницы между Внушительные использованием Create * и * Найти методы. Оба эти метода определены в моем базовом классе PgStore<Model> (а не в PgCourseStore), в то время как я привязываю только объекты ICourseStore и PgCourseStore.

+0

Я не вижу ничего плохого в вашем коде. Предположим, что 'CourseController' зависит от' ICourseStore' через конструктор для установки 'store' и' PgCourseStore', 'CoursesController' все зарегистрированы в контейнере IoC. –

+0

Различные или противоречивые версии сборки в одном проекте? –

+0

@BobDust да, PgCourseStore привязан к ICourseStore и зарегистрирован всем контроллерам. Более того, как я сказал, методы Find * отлично работают, и я не могу понять, почему. Добавлю несколько обновлений, чтобы сделать ситуацию более ясной через 10 минут. –

ответ

2

Это был тип dynamic, который вызвал ошибку привязки во время выполнения. Изменение на object могло бы вам помочь:

public virtual async Task<HttpResponseMessage> Post(object value) 
    { 
     var model = Parse(value); 
     await store.CreateAsync(model); 
     return Request.CreateResponse(HttpStatusCode.Created); 
    } 
+0

О, это имеет смысл. Так много проблем с динамическим типом. Благодаря! –