0

私のアプリケーションでは、サブスクライバーを登録するための何かを提供する単純なイベント ハブを作成しています。

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)、Subscriber にはDataChanged<A>、データがどこに渡された B インスタンスであるかが通知されますDataChanged<B>。したがって、共分散のサポートも必要です。

次のように、Co-/And Contravariance の両方をサポートするライブラリを作成することを考えました。

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

次のような変換(キャストではありません!)が可能になります:

Obj<Fruit, Fruit> x;
IMyObject<Apple, object> x2 = x.ToVariant<Apple, object>();

どう思いますか?出来ますか?動的プロキシを使用してそれを行うことを考えました。

4

2 に答える 2

1

この部分では:

公開するとき は、 -instanceがどこにあるかを通知 Publish<DataChanged<B>>(new DataChanged<B>(new B())する 必要があります。SubscriberDataChanged<A>.DataB

私はあなたを理解していなかったかもしれません-たとえば、何を指しているのかわかりません.Data。BとAの関係を推測することしかできません。BがAから派生しているということですか?

もしそうなら、C#4は必ずしもそのようなことを自動的に起こさせるわけではありません。タイプX<A>X<B>はデフォルトではまったく互換性がありません。Xがでinterfaceあり、型パラメーターがとしてマークさoutれている場合X<B>、型の変数に割り当てることができますX<A>。ただし、これはインターフェイス専用であり、具体的なタイプではないことに注意してください(デリゲートにも同様の規定がありますが、それだけです)。

編集:

したがって、実行したいのは、C#/ CLR 4.0X<B>で型の変数に割り当てることができる方法をシミュレートすることです。ここで、Xはインターフェイスです。X<A>

Xが次のようになっているとします。

interface X<T>
{
    T Foo(int arg);

    // Note: T may only appear as an output, so this is illegal:
    // void Foo(T arg);
}

あなたは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);
    }
}

各メソッドを実際の実装に転送するだけです。

ただし、継承によって関連付けられたジェネリック外部クラスとジェネリックパラメーターのペアの可能なすべての組み合わせに対して、このようなラッパークラスが必要になります。それらをすべて手作業で記述し、特定の状況に適したものを選択するために大規模なルックアップを維持することは、面倒でエラーが発生しやすく、決して完了しないタスクになります。

これで、実行時にラッパークラスを作成するためのコード生成に取り掛かりました。

于 2009-04-01T22:28:23.120 に答える
1

IMO、これは物事を非常に複雑にし、多くのリフレクション コードを書くことになります。C# 4.0 まで待てますか? ;-p

または、コードは、処理方法がわからないものを無視することもできます...

于 2009-04-01T22:10:55.360 に答える