4

API バージョン番号に基づいて内部ルーティングを容易にするために使用している辞書があります。基本的に何が起こるかというと、辞書を調べて操作し、その RUN メソッドを呼び出そうとします。しかし、これを行うには、オブジェクトをそのインターフェイスにキャストできる必要があります。これが私が言いたいことです、これは辞書です:

    public Dictionary<string, Type> Routing = new Dictionary<string, Type>();

    public VersionRouter()
    {
        Routing.Add("1.0", typeof(OperationV1<RequestObjectV1, ResponseObjectV1>));
        Routing.Add("2.0", typeof(OperationV1<RequestObjectV2, ResponseObjectV1>));
        Routing.Add("3.0", typeof(OperationV1<RequestObjectV2, ResponseObjectV2>));
    }

次のように、インスタンス化したい正しいタイプを取得できます。

var myOperation = Routing["2.0"];

そして、通常の状況では、次のようにインスタンス化してキャストします。

var myInstance = (MyInterface) Activator.CreateInstance(myOperation);

ただし、リクエストとレスポンスのタイプが何であるかを知る必要があるため、インターフェースは汎用です。

var myInstance = (MyInterface<TRequest, TResponse>) Activator.CreateInstance(myOperation);

この段階で、これらのリクエストとレスポンスのタイプが何であるかを伝える方法がわかりません。リフレクションでできると思います。myOperation.GetGenericArguments() のようなものを介してこれらの汎用パラメーターを取得できることがわかりましたが、この段階でそれを有利に使用する方法がわかりません。誰もこれを行う方法を知っていますか?

4

2 に答える 2

6

SLaks の回答を拡張するには:

シナリオを処理する論理的な方法はありません。あなたがやろうとしているのは、実行時に単一のコードをさまざまなタイプで機能させることです。これは、別個のコード ブランチを構築する (実行可能) か、ダイナミクス/リフレクションにフォールバックすることによってのみ実行できます。これを明確にするために:

class Apple { }
class Pear { }

void Handle(object what)
{
    // either
    if (what is Apple) {}
    else if (what is Pear) {}

    // or
    dynamic x = what;
    x.LetsHopeThisMethodExists();

    // or
    what.GetType().GetMethod('lorem').Invoke(what, null);
}

Appleこれで、との両方の基本型を宣言するという SLaks の提案Pear、つまりに固執することができますFruit。そうすれば、Handleを受け入れて、とのFruit両方で利用可能な共通機能でロジックを実行できます。ApplePear

これは、ジェネリックでこれを行う方法という疑問を投げかけます。ジェネリックは既定では分散をサポートしていませんが、.NET 4.0 では確実に可能です。out型パラメーターにキーワードを適用することで、インターフェイス (インターフェイスのみ) を共変として宣言できます。これにより、次のようなことができます。

interface IFruit { }
interface IBasket<out TFruit> where TFruit : IFruit { }

class Apple : IFruit { }
class Pear : IFruit { }

class FruitBasket<TFruit> : IBasket<TFruit> where TFruit : IFruit { }
void Handle(IBasket<IFruit> what) { }

Handle(new FruitBasket<Apple>());
Handle(new FruitBasket<Pear>());
于 2012-12-14T06:17:40.203 に答える
5

それは本質的に不可能です。
実行時まで型パラメーターがわからないため、コンパイル時にこの型を表現することはできません。
したがって、それにキャストしたり、その型の変数を持つことはできません。

可能であれば、インターフェイスを共変にし、キャストして基本型を使用する必要があります。

または、非ジェネリックまたは共変の基本インターフェイスを作成して、代わりに使用することもできます。

于 2012-12-14T03:49:17.787 に答える