在我的应用程序中,我正在创建一个简单的事件中心,提供注册订阅者的东西:
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>();
你怎么看?可能吗?想到使用动态代理做到这一点。
答案 0 :(得分:1)
或者,您的代码可能会忽略它不知道如何处理的事情......
答案 1 :(得分:1)
在这部分:
当我发布时
Publish<DataChanged<B>>(new DataChanged<B>(new B())
, 应通知Subscriber
DataChanged<A>
.Data
。B
.Data
- 。实例
我可能没有理解你 - 例如,我看不出X<A>
所指的是什么,我只能猜测B和A之间的关系。你的意思是B来自A吗?
如果是这样,C#4不一定会自动发生这样的事情。默认情况下,X<B>
和X
类型根本不兼容。如果interface
为out
且类型参数标记为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}}
您只需将每个方法转发到实际实现。
但是,对于通用外部类和通过继承相关的通用参数对的每种可能组合,您都需要这样的包装类。这将是一个繁琐,容易出错且永不完成的任务,手动编写它们并保持大查找以针对给定情况选择正确的查找。
所以现在你要进行代码生成以在运行时制作包装类。