1

Ich habe Basis generische SchnittstelleChild-Schnittstelle generische Schnittstelle IoC bindnig in 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); 
} 

und es ist Kind-Schnittstelle

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

wo Course Basismodell Klasse. Ich implementiere dieses Repository mit PgCourseStore : PgStore<Course>, ICourseStore, wobei PgStore<Course> eine Basisklasse für die Arbeit mit Postgres ist.

Ich habe abstrakte Basis Controller-Klasse

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

mit grundlegenden CRUD Methoden und seine untergeordneten Controller mit speziellen Abfragen CoursesController : BaseController<Course, ICourseStore> wo ich store Variable muß ICourseStore sein, spezielle Anfragen zu nennen.

Also, wenn ich versuche, PgCourseStore mit ICourseStore mit verschiedenen IoC-Containern zu binden (wie DryIOC, Autofac) alles funktioniert gut, wenn FindAsync Methoden aus meiner Basissteuerung aufgerufen werden. Aber wenn ich versuche, Update-, Delete- oder Create-Methoden aufzurufen, bekomme ich Microsoft.CSharp.RuntimeBinder.RuntimeBinderException mit der Nachricht, dass ICourseStore keine Definition für die CreateAsync-Methode hat. Ja, ich kann store wie ICRUDStore Typ speichern und es wenn ich brauche, aber kann es sein, gibt es schönere Lösung?

UPD:BaseController sieht aus wie

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

Und CourseController

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

So kann ich keine meaningfull Unterschied * Create zwischen der Verwendung und finden * Methoden. Beide Methoden sind in meiner Basisklasse PgStore<Model> (nicht in PgCourseStore) definiert, während ich nur ICourseStore und PgCourseStore binde.

+0

Ich sehe nichts falsch mit Ihrem Code. Angenommen, 'CourseController' hängt über' ICourseStore' über einen Konstruktor ab, um 'store' und' PgCourseStore' zu ​​setzen, 'CoursesController' sind alle im IoC-Container registriert. –

+0

Verschiedene oder widersprüchliche Assembly-Versionen im selben Projekt? –

+0

@BobDust Ja, PgCourseStore ist mit ICourseStore verbunden und alle Controller sind registriert. Noch mehr, wie ich schon sagte Find * Methoden funktioniert gut und ich kann nicht herausfinden, warum. Ich werde einige Updates hinzufügen, um die Situation in 10 Minuten klarer zu machen. –

Antwort

2

Es war der Typ dynamic, der Laufzeitbindungsfehler verursachte. Ändern zu object könnte Ihnen helfen:

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

Oh, das macht Sinn. So viele Probleme mit dem dynamischen Typ. Vielen Dank! –

Verwandte Themen