将类实例注入通用接口

时间:2015-02-05 23:10:00

标签: c# interface dependency-injection

我有这个模特课:

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>
{}

我的FunctieModel的存储库实现:

public class FunctieRepoSql : IFunctieRepo
{...}

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

public class Tester    
{
    IBaseRepo<ObservableObject> repo;

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

这一切都很好。现在我需要使用不同的存储库来实例化测试器类。

new Tester(new FunctieRepoSql())

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

我显然缺少一些东西。任何人都知道如何让这个工作?

2 个答案:

答案 0 :(得分:1)

您无法将IBaseRepo<FunctieModel>转换为IBaseRepo<ObservableObject>。例如,想象一下猫的通用集合,如果你将它转换成动物集合,你就可以添加一只狗,这是不可取的。但是,您可以在此处使用out关键字:

public interface IBaseRepo<out T> where T : ObservableObject

但是你不能接受ObservableObjects作为输入(msdn about out)。

答案 1 :(得分:0)

您需要考虑两个关键选项。最简单的方法是简单地使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而不是通用版本。