更新:创建了一个简单的解决方案

正如埃里克在下面所说的那样,我有点高兴,但它仍然没有真正解决我的问题。我想出了一个更好的解决方案来从我的核心程序集中删除 MassTransit 依赖项。

我已经在下面详细发布了答案。

原始问题

有没有办法对泛型参数施加约束,说明它必须是具体实现的类型?

现在我正在使用一个单元测试,它进行反射以确保所有实现都正确形成,但我希望它被编译器失败。

例子:

抽象基

// this abstract class extends another generic type that needs to know
// the type of the concrete implementation "TConsumer"
public abstract class ConsumerBase<TMessage,TConsumer> :
    Consumes<AssignedMessage<TMessage,TConsumer>>.All
    where TMessage : IMessage
    where TConsumer : {{The class that's implementing me}}
{

}

应该成功
// this class passes it's own type as a generic arg to it's base
// and it works great!
public class TestConsumer : ConsumerBase<TestMessage, TestConsumer>
{  }

应该失败
// this class passes a different type as a generic arg to its base
// and should FAIL!!! but how?
public class FailConsumer : ConsumerBase<TestMessage, TestConsumer>
{  }

更新:进一步解释

为了进一步解释为什么我要这样做......

我正在尝试创建一个对 MassTransit 的抽象(说起来容易做起来难)。公共(public)交通需要消费者实现 Consume.All。

就我而言,TMessage 是一个 AssignedMessage。

需要使用 AssignedMessage 实现 MassTransit 的通用 Consumes.All 意味着我需要传递通用 TAssignee 参数。

话虽如此,它仍然没有完全抽象出大众运输。它给了我一个公共(public)交通下的基类,它隐藏了我正在实现一个 MassTransit 接口(interface)的事实,但它仍然是一个 MassTransit 依赖项。

最佳答案

正如 Lee 正确指出的那样,这个概念在 C# 类型系统中不存在。你可以接近,但不能完全到达那里。我关于这个主题的文章在这里:

http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx

我建议您患有泛型幸福病,这种情况会导致开发人员尝试在泛型类型和约束的复杂相互作用中捕获所有业务逻辑,而不管这对于该类型的用户来说有多么令人困惑。

泛型类型系统旨在解决“我有一个苹果列表、一个恐龙列表和一个价格列表;我希望所有这些列表共享相同的实现”的问题。您的类型:

public abstract class ConsumerBase<TMessage,TConsumer> :
    Consumes<AssignedMessage<TMessage,TConsumer>>

是对泛型类型系统的滥用。假设您问某人“消息的消费者和消费者是什么?”没有患过通用性幸福病的人会不会说“消息的消费者和消费者是一种消费事物,它消费分配的消息和消费者的消息”?

我的建议是大规模简化系统。您试图在此处的类型系统中捕获太多内容。

关于c# - 抽象出大众运输依赖,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21945701/

10-15 06:16