我应该支持C#3.0中发布/子场景的协同/反演吗?

时间:2009-04-01 19:41:56

标签: c#-3.0 covariance contravariance publish-subscribe

在我的应用程序中,我正在创建一个简单的事件中心,提供注册订阅者的东西:

Subscribes<EventType>(ISubscriber<EventType> subscriber) 
// and some other methods for adding subscribers

发布活动。

Publish<EventType>(EventType @event)

非常简单。我想将Publish<int>(0)路由到实施ISubscriber<int>的所有订阅者。

有什么不太难的,我希望订阅者EventType是逆变的。所以ISubscriber<object>基本上应该消耗所有东西。我不希望他们也消耗掉它们的价值。

使用C#4没问题,但现在我正在用C#3做这些事情并且只是假装与界面相反:

public interface IContravariantGenerics { 
  object AsVariantFor(Type[] genericParamters);
}

好吧,现在,我想将数据转换为像这样的“事件类型”。该事件的通用参数必须是协变的。

SubX : ISubscriber<DataChanged<A>>

DataChanged<T>
  T Data {get;}

当我发布Publish<DataChanged<B>>(new DataChanged<B>(new B())(给定B:A)时,应通过DataChanged<A>通知订阅者,其中Data是传递给DataChanged<B>的B实例。所以我也需要协方差支持。

我想过编写一个支持Co- / And Contravariance的lib,如下所示:

IMyObject<T1, T2> : IWithVariance<In, Out>

允许转换(不是强制转换!),如下所示:

Obj<Fruit, Fruit> x;
IMyObject<Apple, object> x2 = x.ToVariant<Apple, object>();
你怎么看?可能吗?想到使用动态代理做到这一点。

2 个答案:

答案 0 :(得分:1)

IMO,这将使事情变得非常复杂,这意味着你最终会编写大量的反射代码。你能等C#4.0吗? ;-p

或者,您的代码可能会忽略它不知道如何处理的事情......

答案 1 :(得分:1)

在这部分:

  

当我发布时   Publish<DataChanged<B>>(new DataChanged<B>(new B()),   应通知Subscriber   DataChanged<A> .DataB   .Data - 。实例

我可能没有理解你 - 例如,我看不出X<A>所指的是什么,我只能猜测B和A之间的关系。你的意思是B来自A吗?

如果是这样,C#4不一定会自动发生这样的事情。默认情况下,X<B>X类型根本不兼容。如果interfaceout且类型参数标记为X<B>,则可以将X<A>分配给X<B>类型的变量。但请注意,这仅适用于接口,而不是具体类型(代表有类似的规定,但这就是全部)。

修改:

因此,您要做的是模拟在{C#/ CLR 4.0中将X<A>分配给interface X<T> { T Foo(int arg); // Note: T may only appear as an output, so this is illegal: // void Foo(T arg); } 类型的变量的方式,其中X是一个接口。

假设X是:

X<B>

您有X<A>,需要B。您知道A可分配给class WrapX_A_B : X<A> { public X<B> Impl { get; set; } public A Foo(int arg) { return Impl.Foo(arg); } } 。所以你需要以下适配器:

{{1}}

您只需将每个方法转发到实际实现。

但是,对于通用外部类和通过继承相关的通用参数对的每种可能组合,您都需要这样的包装类。这将是一个繁琐,容易出错且永不完成的任务,手动编写它们并保持大查找以针对给定情况选择正确的查找。

所以现在你要进行代码生成以在运行时制作包装类。