将 class 实例注入通用接口

Injecting a class instance to a generic interface

我有这个型号class:

public class FunctieModel: ObservableObject
{ ... }

存储库的基本接口:

public interface IBaseRepo<T> where T : ObservableObject
{
    void Delete(int id);
    T GetItem(int id);
    IEnumerable<T> GetList();
    bool Update(T model);
    bool Insert(T model);
}

FunctieModel 类型存储库的特定接口

public interface IFunctieRepo : IBaseRepo<FunctieModel>
{}

我的 FunctieModels 存储库的实现:

public class FunctieRepoSql : IFunctieRepo
{...}

我的测试人员 class 必须能够使用必须注入的存储库:

public class Tester    
{
    IBaseRepo<ObservableObject> repo;

    public Tester(IBaseRepo<ObservableObject> repo)
    {
        this.repo = repo;
    }
}

这一切编译正常。现在我需要用不同的存储库实例化测试器 class。

new Tester(new FunctieRepoSql())

这就是我的问题所在。错误是
无法从 FunctieRepoSql 转换为 IBaseRepo<ObservableObject>

我显然遗漏了一些东西。任何人都知道我如何让它工作?

您无法将 IBaseRepo<FunctieModel> 转换为 IBaseRepo<ObservableObject>。例如,假设有一个通用集合,假设是猫,如果将其转换为动物集合,则可以向其中添加一只狗,这是不可取的。但是,您可以在此处使用 out 关键字:

public interface IBaseRepo<out T> where T : ObservableObject

但是你将无法接受 ObservableObjects 作为输入 (msdn about out)。

您有两个关键选项需要考虑。最简单的方法是简单地使 Tester 通用并使用一个可以传递给 IBaseRepo<T> 的类型参数。

public class Tester<T> where T : ObservableObject
{
    IBaseRepo<T> repo;

    public Tester(IBaseRepo<T> repo)
    {
        this.repo = repo;
    }
}

那么您可以将调用代码更改为:

new Tester<FunctieModel>(new FunctieRepoSql())

如果出于某种原因您不能使用此技术,您可以改为创建另一个非通用接口,IBaseRepo IBaseRepo<T> 扩展。它应该将等效方法表面化为 IBaseRepo<T>(对于那些使用 T 的方法),而是在不使用该类型参数的情况下声明它们。这类似于 IEnumerableIEnumerable<T>。完成此操作后,您可以让 Tester 在其构造函数中接受 IBaseRepo 而不是通用版本。