3

コンパイルされた.netアセンブリのセットで、特定のクラスに関連付けられたソースファイルを探しています。

例えば

MyAsm.Namespace.Foo  -> C:\Source\foo.cs
MyAsm.Namespace.Bar  -> C:\Source\Code\MoreCode\Common.cs
MyAsm.Namespace2.Bar -> C:\Source\Code\MoreCode\Common.cs
...

標準System.Reflection機能を使用して作業したいタイプ情報をアセンブリリフレクション/抽出しています。

ここで、クラスの元の.csソースファイルを見つける必要があります。回避策としてブルートフォースソリューションを用意していますが、許容できないほど遅いです。

プロセス全体が約5秒で完了することを望んでいます。現在、反射抽出部分の所要時間は1秒未満で、「ファイルの関連付け」には数分かかります。4秒で数MBをスキャンするのは無理だとは思いません。

残念ながら、ショートカットを妨げるいくつかの注意事項があります。

  • ファイルの名前がわからないので、dir / s *.csすべての潜在的なソースファイルを列挙するために、すべての実行を実行する必要があります。

  • クラス名は常にソースファイルと一致するとは限りません。可能な場所を示唆することはできますが、機能することが保証されているわけではありません。

  • 場合によっては、同じファイルに複数のクラスが定義されています。

  • 〜20kの.csファイル/63MBのソースがあります。

  • 〜10kのクラス/それらのファイル間の関連付けが必要です。

  • ファイルの内容が変更されるため、ファイル名/クラスが宣言されたDBを段階的に構築したくないので、このDBなどを維持するのに問題があります(ただし、すべての場合、このルートをたどる必要があるかもしれません)それ以外の場合は失敗します)。

  • OSのこれは実行され、Windowsサーチ/インデックス作成が有効になっていないので、そこにも喜びはありません。

私が試したこと:

  • findstr.exeの使用-遅すぎる

  • .netアプリを作成し、すべてのファイルをメモリにロードします。-遅すぎて*.csを見つけることができず、すべてのファイルをロードできません。ファイルがメモリに入ったらスキャンするのは高速です。

  • すべての小さなファイルから1つの大きなソースファイルを作成し、それをロードし、スキャンするなど、やはり遅すぎます。ファイルのビルドには数分かかります。ロードすると高速になります。

  • PDBファイルの読み取り-PDB2XML.exeを調査しています。ファイル名を出力し、高速に実行されますが、クラスをファイル名に関連付ける方法がわかりません。

それで、誰かが別の提案、魔法、またはPDB2XMLの経験を持っていますか?

4

4 に答える 4

2

これは、任意のクラスのファイルパスを取得したいので、直面している問題を正確に解決するわけではありませんが、ソースの場所からファイルへのポインターを取得するだけで、私の使用では簡単に機能します。私はこれを単体テストで使用しているので、パフォーマンスはそれほど重要ではありません。

var x = new StackTrace(true);
var file = x.GetFrame(0).GetFileName();
于 2013-06-27T17:54:30.003 に答える
1

ファイルがディスク上にある場合は、PDBを使用するのが最善の選択肢です。ファイル名( ISymbolDocument.URLで表される)は、シーケンスポイントに関連しています。シーケンスポイントは、クラスではなく、メソッド(プロパティのget / setを含む)に関連しています。もちろん、.NETクラスのソースは複数のファイルに保存できます。したがって、対応するすべてのファイルを判別するには、あるタイプのすべてのメンバーを参照する必要があります(たとえば、リフレクションを使用)。

于 2012-10-24T14:35:37.680 に答える
1

ソースを編集できる場合。リフレクションとSystem.Runtime.CompilerServices.CallerFilePathを使用してこれを行うことができます。各ファイルのソースに属性を追加するだけです。部分的なクラスには、何か賢いことを考える必要があるかもしれません。

このサンプルは、属性が配置されたソースファイルと行番号を提供します。

[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = false)]
public sealed class SourceInfoAttribute : Attribute
{
    public SourceInfoAttribute([CallerLineNumber]int sourceLineNumber = 0, [CallerFilePath] string sourceFilePath = "")
    {
        SourceLineNumber = sourceLineNumber;
        SourceFilePath = sourceFilePath;
    }

    internal int SourceLineNumber { get; set; }
    internal string SourceFilePath { get; set; }
}    
于 2019-07-26T18:23:43.927 に答える
0

.NETのファイル名とアセンブリ名の間に関係があることを私は知りません。実際、1つのファイルに複数のアセンブリが定義されている可能性があるため、各ソースコードを物理的に表示せずにこれを行う方法がわかりません。ファイルを作成し、クラス定義を検索するか、実行中のインデックスを維持します。

于 2012-10-24T14:12:08.423 に答える