繁体   English   中英

在C#中使用泛型-从泛型类调用泛型类

[英]Using Generics in C# - Calling Generic class from a Generic class

我有一个类似于以下课程:

public abstract class Manager<T, TInterface> : IManager<T> where TInterface : IRepository<T>
{
    protected abstract TInterface Repository { get; }

    public virtual List<T> GetAll()
    {
        return Repository.GetAll();
    }
}

这样做非常好,但是,有一种方法可以避免在抽象类声明和扩展我的通用抽象类的结果类中使用TInterface:

public class TestManager : Manager<TestObject, ITestRepository>, ITestManager

我被迫使用ITestRepository并使Repository属性变得抽象,这是因为它可能包含我需要了解并能够调用的自定义方法。

当我继续构建层时,我将不得不一直在整个堆栈中执行此过程。 例如,如果我有一个通用的抽象控制器或服务层:

public class TestService : Service<TestObject, ITestManager>, ITestService

有没有更好的方法可以做到这一点,或者这是允许通用类调用另一个通用类的最佳实践?

似乎您要做的只是使Manager<T>可测试,并使用模拟作为可查询特殊成员的存储库。

如果是这样,也许您可​​以将设计更改为:

public class Manager<T> : IManager<T> {
  protected IRepository<T> Repository { get; set; }
  // ...
  public virtual List<T> GetAll() {
    return Repository.GetAll();
  }
}

现在,所有测试的细节都在一个测试子类中:

public class TestingManager<T> : Manager<T> {
  public new ITestRepository<T> Repository {
    get {
      return (ITestRepository<T>)base.Repository;
    }
    set {
      base.Repository = value;
    }
  }
}

编写单元测试时,将创建TestingManager<T>实例(通过TestingManager<T>声明的变量和字段进行引用),并为它们提供测试存储库。 每当您查询他们的Repository ,总会得到一个强类型的测试存储库。

更新:

没有子类,还有另一种解决此问题的方法。 您将存储库对象声明为传递给Manager<T>的测试存储库,然后直接查询它们,而无需通过Manager<T>

[Test]
public void GetAll_Should_Call_GetAll_On_Repository_Test() {
  var testRepository = new TestRepository();
  var orderManager = new Manager<Order>(testRepository);
  // test an orderManager method
  orderManager.GetAll();
  // use testRepository to verify (sense) that the orderManager method worked
  Assert.IsTrue(testRepository.GetAllCalled);
}

不,你无法解决它。 您可以尝试,但结果会很丑陋,并且在某种程度上不正确。 原因是您要求泛型不泛型,但仍然是泛型。

如果新类使用继承或组合形式的泛型类,并且它本身对所使用的泛型类的类型参数的了解不多,则它本身必须是泛型的。 类似于方法调用链,其中方法可以将参数传递给另一个方法。 它不能构成inner方法的参数,而必须从确实知道它们是什么的调用方将它们本身当作参数。 类型参数相同。

有一件事确实让这感觉就像代码味道的是,你不能有类型管理器<,>的变量的事实。 它必须是完全类型指定的。 我想出的一种解决方案是拥有泛型类实现的非泛型接口。 这些接口尽可能具有泛型类的公共接口(它们不能具有引用类型参数的方法或属性)。 然后,您可以传递接口类型的变量,而不必指定类型参数。

例:

interface IExample {
    string Name { get; }
    void SomeNonGenericMethod(int i);
}

class Example<T> : IExample {
    public string Name { get { ... } }

    public void SomeNonGenericMethod(int i) {
        ...
    }

    public T SomeGenericMethod() {
        ...
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM