レジストリへのアクセスは非常に複雑です。あなたは基本的に大きな二分木を読んでいます。クラスの設計は、保存されているデータ構造に大きく依存する必要があります。そうして初めて、適切なクラス設計を選択できます。柔軟性を維持するには、REG_SZ、REG_EXPAND_SZ、DWORD、SubKeyなどのプリミティブをモデル化する必要があります。DonSymeの著書Expert F#には、バイナリコンビネータを使用したバイナリ解析に関する優れたセクションがあります。基本的な考え方は、オブジェクトがバイナリ表現から逆シリアル化する方法を自分で知っているということです。このように構成されたバイトのストリームがある場合
<Header> <Node1 />
<Node2> <Directory1>
</ Node2> </ Header>
BinaryReaderから始めて、バイナリオブジェクトをバイトごとに読み取ります。最初のものはヘッダーでなければならないことがわかっているので、それをHeaderオブジェクトに渡すことができます
public class Header
{
static Header Deserialize(BinaryReader reader)
{
Header header = new Header();
int magic = reader.ReadByte();
if( magic == 0xf4 ) // we have a node entry
header.Insert(Node.Read( reader );
else if( magic == 0xf3 ) // directory entry
header.Insert(DirectoryEntry.Read(reader))
else
throw NotSupportedException("Invalid data");
return header;
}
}
パフォーマンスを維持するために、たとえば、このインスタンスまたはそのインスタンスの特定のプロパティが実際にアクセスされるまで、データの解析を遅らせることができます。
Windowsのレジストリは非常に大きくなる可能性があるため、一度に完全にメモリに読み込むことはできません。チャンクする必要があります。Windowsが適用する1つの解決策は、ファイル全体が数ギガバイトにまたがることができるページプールメモリに割り当てられますが、実際にアクセスされた部分のみがディスクからメモリにスワップアウトされることです。これにより、Windowsは非常に大きなレジストリファイルを効率的に処理できます。読者にも似たようなものが必要になります。遅延解析は1つの側面であり、間にデータを読み取る必要なしにファイル内をジャンプする機能は、パフォーマンスを維持するために非常に重要です。
ページングプールとレジストリの詳細については、http:
//blogs.technet.com/b/markrussinovich/archive/2009/03/26/3211216.aspxを参照してください。
Apiの設計は、効率を維持するためにデータを読み取る方法によって異なります(たとえば、メモリマップトファイルを使用して、異なるマップされた領域から読み取る)。.NET 4では、メモリマップトファイルの実装が登場しました。これは非常に優れていますが、OSAPIのラッパーも存在します。
あなたの、アロイス・クラウス
メモリマップトファイルからの遅延ロードをサポートするには、バイト配列をオブジェクトに読み込んで後で解析するのではなく、さらに一歩進んで、メモリマップトファイルからのメモリチャンクのオフセットと長さのみを格納するのが理にかなっています。後でオブジェクトに実際にアクセスしたときに、データを読み取って逆シリアル化できます。このようにして、ファイル全体をトラバースし、オフセットとメモリマップトファイルへの参照のみを含むオブジェクトのツリーを構築できます。これにより、大量のメモリを節約できます。