【问题标题】:Child interface of generic interface IoC bindnig in c#c#中泛型接口IoC bindnig的子接口
【发布时间】:2023-04-03 03:38:01
【问题描述】:

我有基本的通用接口

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&lt;Course&gt;, ICourseStore 实现这个存储库,其中 PgStore&lt;Course&gt; 是使用 Postgres 的基类。

我有抽象的基本控制器类

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

使用基本 CRUD 方法及其带有特殊查询的子控制器 CoursesController : BaseController&lt;Course, ICourseStore&gt; 我需要将 store 变量设为 ICourseStore 来调用特殊查询。

因此,当我尝试将 PgCourseStoreICourseStore 与不同的 IoC 容器(如 DryIOC、Autofac)绑定时,当从我的基本控制器调用 FindAsync 方法时,一切正常。但是,当我尝试调用 Update、Delete 或 Create 方法时,我收到 Microsoft.CSharp.RuntimeBinder.RuntimeBinderException 消息,表明 ICourseStore 没有 CreateAsync 方法的定义。 是的,我可以像 ICRUDStore 类型一样存储 store 并在需要时进行转换,但可能有更漂亮的解决方案吗?

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* 和 Find* 方法之间有任何有意义的区别。这两种方法都在我的基础 PgStore&lt;Model&gt; 类中定义(不在 PgCourseStore 中),而我只绑定 ICourseStore 和 PgCourseStore。

【问题讨论】:

  • 我认为您的代码没有任何问题。假设CourseController依赖ICourseStore通过构造函数设置storePgCourseStoreCoursesController都注册到IoC容器。
  • 同一个项目中有不同或冲突的程序集版本?
  • @BobDust 是的,PgCourseStore 与 ICourseStore 绑定并且所有控制器都已注册。更重要的是,正如我所说的 Find* 方法工作正常,我不知道为什么。 '将在 10 分钟内添加一些更新以使情况更加清晰。
  • @TravisIllig 没有得到你的问题,抱歉。就像引用两个具有相同方法/类/等的 dll 一样。在同一个命名空间中?如果是这样,那么没有。除了默认的 WebApi 之外,我根本没有引用任何内容。加上 autofac 或 dryioc(不能同时使用)。
  • @TonyYoung,你是如何编译上面更新的BaseController的?其构造函数中的参数类型必须是Store

标签: c# asp.net-web-api dependency-injection inversion-of-control autofac


【解决方案1】:

dynamic 类型导致了运行时绑定错误。更改为 object 可以帮助您:

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

【讨论】:

  • 哦,有道理。动态类型有很多麻烦。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多