Share via


カスタム リゾルバの作成

このトピックでは、XmlUrlResolver クラスを拡張してハード ディスクにストリームをキャッシュする例を示します。GetEntity を呼び出すたびに、その GetEntity メソッドによって返されたストリームが c:\temp ディレクトリに保存されます。この方法は、ネットワークを通じてリソースを解決するときに有効です。キャッシュ処理では GetEntity メソッドをオーバーライドします。

カスタム XmlResolver では、.NET Framework Version 1.1 に含まれている XmlSecureResolver ではなく、XmlUrlResolver を使用しているため、リダイレクト時に先方のドメインのチェックが行われません。つまり、外部エンティティなどを参照している includesimports によってリダイレクトが発生するような埋め込み URI があると、データやサイトのセキュリティを一切チェックせずに、データが読み込まれてしまうことになります。これは、リダイレクト時に資格情報が渡されないことが原因であり、安全でないサイトや匿名サイトからデータが取得されることによって、アプリケーションのセキュリティが低下する場合があります。

下に示すコード例では、静的な Hashtable である myHash に、解決済みの URI の情報を格納します。URI が最初に解決されるときには、ストリームがファイルに格納され、そのファイルを表すストリームが返されます。また、Hashtable には、URI をキーとして使用し、ファイル名を値とするエントリが作成されます。その URI の 2 回目以降の解決時には、Hashtable がチェックされて、ハード ドライブに現在キャッシュされているストリームが使用されます。異なるプロセス上でこのクラスの複数のインスタンスが実行されている場合は、複数のファイル名がそれぞれ確実に一意になるようにするための追加のコードが必要です。次の例では、フォルダ c:\resolver_cache が存在することを前提としています。このクラスの完全なコード例を次に示します。

Class CustomResolver
Inherits XmlUrlResolver
Public Shared myHash As New Hashtable()

Public Sub New()
End Sub 'New
      
Public Overrides Function GetEntity(absoluteUri As Uri, role As String, ofObjectToReturn As Type) As Object
If myHash.ContainsKey(absoluteUri) Then
    Console.Out.WriteLine(("Reading resource" + absoluteUri.ToString() + " from cached stream"))
    'Returns the cached stream.
    Return New FileStream(CType(myHash(absoluteUri), [String]), FileMode.Open, FileAccess.Read, FileShare.Read)
Else
    ' The filename that the cached stream is stored to.
    Dim filename As [String] = "c:\resolver_cache\resolve" + CStr(myHash.Count) + ".txt"
    Console.Out.WriteLine(filename)
    ' Create a new stream representing the file to be written to,
    ' and write the stream cache from the external
    ' location to the file.
    Dim fStream As New FileStream(filename, FileMode.Create)
    Dim sRead As New StreamReader(CType(MyBase.GetEntity(absoluteUri, role, ofObjectToReturn), Stream))
    Dim sWrite As New StreamWriter(fStream)
    sWrite.Write(sRead.ReadToEnd())
    ' Add the information about the cached Uri to the hashtable.
    myHash.Add(absoluteUri, filename)
    ' Close any open streams.
    sWrite.Close()
    sRead.Close()
    Return New FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read)
    End If
  End Function 'GetEntity
End Class 'CustomResolver
[C#]
class CustomResolver : XmlUrlResolver
{
public static Hashtable myHash=new Hashtable();
public CustomResolver()
{
}
override public object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
{
if(myHash.ContainsKey(absoluteUri))
    {
    Console.Out.WriteLine("Reading resource"+absoluteUri.ToString()+" from cached stream");
    // Returns the cached stream.
    return new FileStream((String)myHash[absoluteUri],FileMode.Open,FileAccess.Read,FileShare.Read);
    }
else
    {
    // The filename that the cached stream will be stored to.
    String filename = "c:\\resolver_cache\\resolve"+myHash.Count+ ".txt";
    Console.Out.WriteLine(filename);
    // Create a new stream representing the file to be written to,
    // and write the stream cache the stream
    // from the external location to the file.
    FileStream fStream = new FileStream(filename, FileMode.Create);
    StreamReader sRead = new StreamReader((Stream)base.GetEntity(absoluteUri, role, ofObjectToReturn));
    StreamWriter sWrite = new StreamWriter(fStream);
    sWrite.Write(sRead.ReadToEnd());
    // Add the information about the cached Uri to the hashtable.
    myHash.Add(absoluteUri,filename);
    // Close any open streams.
    sWrite.Close();
    sRead.Close();
    return new FileStream(filename, FileMode.Open,FileAccess.Read,FileShare.Read); 
    }
  }
}

http://https://、および file:// 以外のプロトコルを使用するリソースを解決するためにカスタム リゾルバを作成する場合は、それらの接続を処理できるように GetEntity メソッドをオーバーライドする必要があります。

baseUri として異なる URI を使用する場合は、メソッドに渡されるパラメータに関係なく固定の baseURI を使用するように、ResolveUri メソッドをオーバーライドする必要があります。たとえば、特定の baseURI を使用してすべての URI を解決するように設定する場合に、新しいプロパティ BaseURI を作成する方法を次のコード例に示します。

Dim baseUri As Uri

Public Property BaseURI() As Uri
   Get
      Return baseUri
   End Get
   Set
      baseUri = value
   End Set
End Property
[C#]
Uri _baseUri;
public Uri BaseURI
{
    get{ return _baseUri;}
    set{ _baseUri = value;}
   }

このプロパティを使用することで、ResolveUri プロパティを次のようにオーバーライドできます。

Public Overrides Function ResolveUri(baseUri As Uri, relativeUri As [String]) As Uri
   Return MyBase.ResolveUri(BaseURI, relativeUri)
End Function 'ResolveUri
[C#]
public override Uri ResolveUri(Uri baseUri, String relativeUri)
    {
        return base.ResolveUri(BaseURI,relativeUri);
    }

参照

URI 名を持つ外部 XML リソースの解決 | XmlResolver を使用したリソースの解決 | ファイルからの読み取り時の XmlResolver への資格情報の提供