2

サードパーティの dll を参照する C# dll があります。サードパーティの dll にはさまざまなバージョンがあります。

ご想像のとおり、最新のサード パーティの dll が存在する場合は新しい機能を使用したいのですが、そうでない場合は古い機能を実行したいと考えています。

これを実現する方法がわかりませんでしたが、最初に試すことは、呼び出す関数を決定する単純な if ステートメントになると思いました。

したがって、アセンブリを見つけて、その場所を取得し、そのバージョン情報を取得します。(製品のバージョンは同じなので、ファイルのバージョンが必要です)。

次に、単純な

if (version >= 3) do x() else do y()

バージョン 2 がインストールされているマシンでコードを実行すると、関連するMissingMethodExceptionメッセージが表示されx()ます。私はばかげた間違いを犯したと思ったが、論理は正しかった。バージョンは2なのでx();実行しないでください。問題のあるメソッドを削除して、に置き換えることにしましたthrow new Exception()。例外はスローされず、コードは正常に完了します。

ここに危険があります-これは分岐予測によるものだと考えています。これは私が知識を持っている分野ではないため危険です。したがって、仮定を立てることは危険なことです。

だから私の質問は:

私はこの問題に間違った方法で取り組んでいますか?私が見逃しているより明白な解決策はありますか?

また

分岐予測を無効にする方法はありますか (それが原因である場合)、続行する前に実行する必要があるポイントとして if 条件を強制/フラグ付けする方法はありますか?

実行中のコードは次のとおりです。

  • バージョン 3 がインストールされているマシンでは問題ありません。
  • バージョン 2 がインストールされているマシンでは、MissingMethodException関連メソッドが取得されx()ます。
  • への呼び出しを削除しx();、例外のスローをコメント解除すると、例外はスローされません。

関連コード:

Assembly assembly = System.Reflection.Assembly.GetAssembly(typeof(3rdPartyClass));
FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location);

if (fileVersionInfo.FileMajorPart >= 3)
{
    // throw new Exception("aagghh");
    x();
}
else
{
    y();
}
4

3 に答える 3

2

リフレクションを使用すると、特定の DLL (具体的には Type) で使用できるメソッドのリストを取得できます。

Vlad のソリューションで指定されているように、この methodinfo を使用してメソッドを動的に呼び出すことができます。

実際、バージョン チェックを省略して、目的のメソッドを直接検索することもできます。

var methodX = assembly.GetType("sometype").GetMethod("X");
if (methodX != null)
{
    methodX.Invoke(params);
}
else
{
    assembly.GetType("sometype").GetMethod("Y").Invoke(otherParams);
}

編集:これはまさにあなたが望むものではありませんが、この種のリフレクションを使用すると、独自のアセンブリに対しても正しいメソッドを見つけることができます。

于 2012-11-08T11:52:30.550 に答える
1

「分岐予測」はありません。メソッドが実行されると、ランタイム バインディングが発生するようです。

したがって、回避策は次のようになります。

if (fileVersionInfo.FileMajorPart >= 3)
{
    CallX();
}
else
{
    CallY();
}

void CallX()
{
    DependentClass.X();
}

void CallY()
{
    DependentClass.Y();
}

ただし、とにかくこれはハックのようです。リンクしている DLL のバージョンで実行する必要があります。

于 2012-11-08T11:49:52.610 に答える
0

これは実際にはより正確な答えです:

        Assembly assembly = System.Reflection.Assembly.GetAssembly(typeof(String));
        FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location);

        ObjectHandle oh = Activator.CreateInstanceFrom("AssemblyName.dll", "namespace.class");
        object o = oh.Unwrap();
        Type to = o.GetType();

        if (fileVersionInfo.FileMajorPart >= 3)
        {
            to.InvokeMember("Method X", BindingFlags.InvokeMethod, null, o, null);
        }
        else
        {
            to.InvokeMember("Method Y", BindingFlags.InvokeMethod, null, o, null);
        }
于 2012-11-08T11:58:10.870 に答える