使用通用接口配置常规工作流程

时间:2017-05-30 15:29:12

标签: c# .net generics .net-4.5

我们最近偶然发现了数据收集计划中的一个问题。我们使用通用接口来创建一个通用工作流程,通过配置中的具体实现,可以轻松地为不同的数据输入进行定制。最近针对缺失数据错误的修复程序通常如下所示:

[TestFixture]
internal class GenericsTest
{
    [Test]
    public void Config()
    {
        new Collector(new Search());
    }
    internal class Collector
    {
        public Collector(Clues<Where, What> foo)
        {

        }
    }
    internal interface Clues<T, P>
    {

    }
    internal class Search : Clues<Where, Item>
    {

    }
    internal class Where
    {

    }
    internal class Item : What
    {

    }

    internal interface What
    {

    }

}

Config正在使用特定搜索初始化特定收集器。收集器本身只期望具有具体类的通用接口Where和interface作为参数。 Search类应该通过实现具有Where类的通用Clues接口和本身实现What接口的Item类来满足这些期望。 相反,搜索的初始化失败,因为它无法在特定实现和一般期望之间建立连接。

Error   CS1503  Argument 1: cannot convert from 'UnitTest.GenericsTest.GenericsTest.Search' to 'UnitTest.GenericsTest.GenericsTest.Clues<UnitTest.GenericsTest.GenericsTest.Where, UnitTest.GenericsTest.GenericsTest.What>'

我们尝试转换为所需的类型,但它只将错误转移到运行时。

一般概念是,工作流保持尽可能通用,配置负责所有特定要求。所需的具体方法应该在item类中引入并隐藏在接口后面,以避免不必要的混乱。

有没有一种特定的方法在C#中编写这样的实现?

1 个答案:

答案 0 :(得分:3)

您必须更改Clues的定义 并使用covariance

  

协方差:   使您可以使用比最初指定的更多派生类型

internal interface Clues<T, out P>

修改

如果您无法更改界面,那么您可以更改Collector类以使用带有约束的泛型:

internal class Collector<TWhere,TWhat> where TWhere:Where where TWhat:What
{
    public Collector(Clues<TWhere, TWhat> foo)
    {

    }
}

然后,您必须准确指定您要使用的类型:

public void Config()
{
    new Collector<Where,Item>(new Search());
}