web-dev-qa-db-ja.com

C#リフレクションとすべての参照の検索

DLLファイルが指定されている場合、そのDLLファイル内のメソッドへのすべての呼び出しを見つけることができます。これを行うにはどうすればよいですか?

基本的に、Visual Studioが既に行っていることをプログラムでどのように実行できますか?

これを行うために 。NET Reflector のようなツールを使用したくありませんが、反射は問題なく、おそらく必要です。

37
user420667

メソッドMyClass.Foo()が使用されている場所を見つけるには、MyClassを含むアセンブリへの参照を持つすべてのアセンブリのすべてのクラスを分析する必要があります。このコードがどのように見えるかについての簡単な概念実証を書きました。私の例では、Jb Evainによって作成された this library (それは 単一の.csファイル です)を使用しました。

私は分析するための小さなテストクラスを書きました:

_public class TestClass
{
    public void Test()
    {
        Console.WriteLine("Test");
        Console.Write(10);
        DateTime date = DateTime.Now;
        Console.WriteLine(date);
    }
}
_

そして、私はTestClass.Test()内で使用されるすべてのメソッドを出力するためにこのコードを書きました:

_MethodBase methodBase = typeof(TestClass).GetMethod("Test");
var instructions = MethodBodyReader.GetInstructions(methodBase);

foreach (Instruction instruction in instructions)
{
    MethodInfo methodInfo = instruction.Operand as MethodInfo;

    if(methodInfo != null)
    {
        Type type = methodInfo.DeclaringType;
        ParameterInfo[] parameters = methodInfo.GetParameters();

        Console.WriteLine("{0}.{1}({2});",
            type.FullName,
            methodInfo.Name,
            String.Join(", ", parameters.Select(p => p.ParameterType.FullName + " " + p.Name).ToArray())
        );
    }
}
_

それは私に次の出力を与えました:

_System.Console.WriteLine(System.String value);
System.Console.Write(System.Int32 value);
System.DateTime.get_Now();
System.Console.WriteLine(System.Object value);
_

この例は、refパラメータとoutパラメータを処理せず、一般的な引数を処理しないため、明らかに完全ではありません。他の詳細も忘れてしまったと思います。それができることを示しているだけです。

50
Elian Ebbing

リフレクションだけでは、特定のアセンブリ内のメソッドへのすべての参照を見つけるのに十分ではありません。リフレクションは、特定のメソッド( MethodInfo.GetMethodBody.GetILAsByteArray )の本体のバイト配列を提供します。他のメソッドへの参照について、自分で解析する必要があります。いくつかの公開されている「 [〜#〜] cil [〜#〜] リーダー」ライブラリがあります(私はそれらを使用していません-うまくいけば誰かがもっと投稿するでしょう)。

FxCop オプションの追加-シナリオによっては、FxCop(Visual Studioコード分析)によって提供されるCIL解析ロジックを再利用し、コード分析の一部として実行しても問題がない場合はカスタムルールを追加できる場合があります。君は。

3
Alexei Levenkov

MSDNマガジンの記事。NETアセンブリとメソッド参照の決定をご覧ください。

3
Darin Dimitrov

Visual Studioアセンブリを反映することを検討し、リバースエンジニアリングされたコードベースでそれが見つかるかどうかを確認します。 VSは実際にはコードをナビゲートしているのではなく、反映していると思います。反射は、マイケルが投稿したように、アセンブリのビットを決定するのに最適ですが、それらのビットのコンシューマではありません。しかし、私は自分の疑いを確認するために反省を再検討していません。

1

こんにちは、現在のアセンブリのすべての呼び出しを検索することを想定した例です。これをコーディングして、いくつかのデフォルト値を持つメソッドにいくつかの制約を設定するために、パラメーター値を取得しようとしました。しかし、パラメーター値を取得することができず、タイプとデフォルトしか取得できませんでした。

var currentAssembly = Assembly.GetExecutingAssembly();

foreach (var method in currentAssembly.GetTypes().Where(type => type.IsClass)
                                      .SelectMany(cl => cl.GetMethods())
                                      .OfType<MethodBase>()
                                      .SelectMany(mb => mb.GetInstructions())
                                      .Select(inst => inst.Operand).OfType<MethodInfo>()
                                      .Where(mi => mi.Name == "<YourMethodName>"))
{
    //here are your calls.
}

それが役に立てば幸い。