ブリッジを作る

全てのブリッジはIBridgeインターフェースを実装します。このインターフェースを実装するクラスが「ブリッジ」と呼ばれます。インターフェースの詳細についてはAPIリファレンスを参照してください。ここでは、インターフェースを実装するに当たって注意すべき点と、実装したブリッジクラスの使用方法について説明します。

説明の前に、DavServerが実装されているアセンブリを入手する必要があります。以下からダウンロードしてください。このアセンブリにはAPIリファレンスで説明されている全てのクラスとインターフェースが含まれています。

ダウンロード

ダウンロード

Kasasagi.DavServer.zip

ダウンロードしたZIPファイルを解凍すると、アセンブリ本体である"Kasasagi.DavServer.dll"と、そのAPIドキュメントである"Kasasagi.DavServer.xml"の2つが抽出されます。この内の"Kasasagi.DavServer.dll"を参照して使用しますが、このアセンブリは.NET Standard 2.0を対象に構築されているため、どのバージョンの.NETと組み合わせても、大抵は動作するはずです。対応している.NETバージョンについては.NET Standardで確認してください。

実装の注意点

IBridgeインターフェースは多くのメソッドを持ちますが、これらの内、GetNodeメソッドとGetNodesメソッドは返戻値としてINode型のオブジェクトを返します。INodeも又、インターフェースであるため、開発者はこれも実装しなければなりません。しかし、実際に実装するのはINodeインターフェースを継承したIDirectoryインターフェースとIFileインターフェースです。少しややこしいため、これらの関係について説明が必要です。

IDirectoryインターフェースとIFileインターフェースは、その名の通り、ディレクトリとファイルを表すインターフェースです。そしてGetNodeメソッドやGetNodesメソッドが返す値はこれらの内のどちらかです。どちらを返すかはメソッドに渡された引数によるため、返戻値の型をディレクトリ、あるいはファイルと決めて掛かることはできません。返せるのは、ディレクトなのかファイルなのかが分からない、ディレクトリツリー内の「ノード」ということになります。このノードは、ディレクトリとファイルに共通の部分だけを持つINodeインターフェースとして表現されます。ディレクトリとファイルはそこから派生したインターフェースです。

ファイルやディレクトには作成日時や更新日時が付き物です。この「日時」には注意が必要です。これらの日時は必ずUTC(協定世界時)でなければなりません。大したことではないように思えますが、サーバーによっては返す日時がどのタイムゾーンのものなのか、よく分からない場合があるのです。タイムゾーンが間違っていても、エクスプローラーで表示される日時が狂うだけならば些細(ささい)なことです。しかし、それだけでは済まないかもしれません。日時による検索が難しくなるため、時に混乱を招くかもしれません。

ファイルやディレクトリの派生元であるINodeには、エクスプローラーと密接な関係にあるプロパティが含まれています。ArchivingプロパティとHiddenプロパティ、そしてReadOnlyプロパティです。エクスプローラーでファイルを右クリックして「プロパティ(R)」を選択すると、そのファイルのプロパティウィンドウが開きます。この中に「読み取り専用(R)」チェックボックスと「隠しファイル(H)」チェックボックスを見て取ることができます。(さら)に、「詳細設定(D)...」をクリックしてみてください。「ファイルをアーカイブ可能にする(A)」というチェックボックスが存在します。「ファイルをアーカイブ可能にする(A)」チェックボックスはArchivingプロパティに、「隠しファイル(H)」チェックボックスはHiddenプロパティに、「読み取り専用(R)」チェックボックスはReadOnlyプロパティに結び付けられます。プロパティウィンドウで「ファイルをアーカイブ可能にする(A)」チェックボックスの値を変更すると、IBridgeインターフェースのSetArchivingAttributeメソッドが呼び出されます。開発者はこの実装の中でArchivingプロパティを変更しなければなりません。同様に、SetHiddenAttributeメソッドの実装でHiddenプロパティを、SetReadOnlyAttributeメソッドの実装でReadOnlyプロパティを変更します。問題は、サーバーのディレクトリツリーが、これらに対応する属性を保有していない、あるいは属性の変更を受け付けない場合があるということです。通常、サーバー上の隠しファイルを普通のファイルに変更するなど考えられません。読み取り専用のファイルを読み書き可能にするようなアクセス許可の変更を、サーバーは認めるでしょうか。「ファイルをアーカイブ可能にする(A)」はバックアップソフトなどが使用するフラグですが、クライアントがサーバーのファイルシステムをバックアップするなどということが、果たして想定されているでしょうか。メソッドの実装に当たって、これらのプロパティを変更できないという事態が予想されます。それにも関わらず、プロパティウィンドウでチェックボックスの値を変更すると、エクスプローラーの側では変更されたことになってしまい、チェックボックスの表示とプロパティの値との間で不整合が生じます。残念ながら、これは回避できない問題です。

サーバーに長時間接続していると、タイムアウトにより、いつの間にか接続が切断されていることがあります。IBridgeインターフェースの各メソッドを実装する際には、メソッドの冒頭で必ず、接続が切断されていないことを確認する必要があります。もし切断されていた場合は、その時点でメソッドを終了するのではなく、明示的に再接続して処理を継続してください。場合によっては、メソッドの途中で接続が切断されることもあり得ます。この点には注意を要します。

ブリッジの使用法

作成したブリッジを使用する方法は簡単です。そのインスタンスをServerクラスのコンストラクタに引き渡し、Startメソッドを呼び出すだけです。ここでは、以下からダウンロードしたRamBridgeという名のブリッジを使用して、起動したDavServerにアクセスする様子を見ていきます。

ダウンロード

ダウンロード

Kasasagi.DavServer.RamBridge.zip

ソースファイルは提供されていませんが、RamBridgeは実に単純なブリッジです。サーバーに接続する代わりに、ローカルメモリ上に構築されたディレクトリツリーにアクセスします。ローカルメモリにアクセスするだけであるため、IBridgeインターフェースの各メソッドの実装も比較的簡素です。サーバーへの接続に使用されるConnectメソッドは事実上、何も行わず、ただ、ルートディレクトリを示す文字列"/"を返すのみです。本来、各メソッドの実装に必要となる冒頭での接続確認も必要無いため、それも省かれています。この単純なブリッジの使用方法を例に、プログラムの記述方法を、順を追って説明します。

  1. "Kasasagi.DavServer.dll"と"Kasasagi.DavServer.RamBridge.dll"の2つのアセンブリをプロジェクトから参照。

  2. 名前空間をインポート。

    C#
    using System.IO;
    using System.Net.Http;
    using Kasasagi.DavServer;
    using Kasasagi.DavServer.RamBridge;

    以下でSystem.IO.FileクラスとSystem.Net.Http.HttpClientクラスを使用するため、System.IO名前空間とSystem.Net.Http名前空間も同時にインポートしています。

  3. RamBridgeのインスタンスを引数としてServerオブジェクトを生成。

    C#
    RamBridge bridge = new RamBridge();
    Server server = new Server(bridge);

    本来であれば、ブリッジのコンストラクタに接続先のホスト名やユーザー名などを引き渡すところですが、RamBridgeのコンストラクタに引数はありません。設定すべきことが何も無いためです。

  4. DavServerを起動。

    C#
    server.Start();

    起動したDavServerは別スレッドでクライアントからのクエリを待ちます。

  5. UNCを指定してファイルやディレクトリにアクセス。

    C#
    string path = Path.Combine(server.Unc, "test.txt");
    File.WriteAllText(path, "xyz");

    if (File.Exists(path))
    {
        Console.WriteLine(File.ReadAllText(path));
    }

    通常のファイルシステムにアクセスするのと同じ手法で、DavServerにアクセスできます。ここではSystem.IO.Fileクラスを使用して、"xyz"と書き込んだ"test.txt"という名前のファイルを生成し、そのファイルを読み込んでいます。

    注意

    RamBridgeを使用したDavServerは、あたかもRAMディスクであるかのように見えます。RAMディスクはメモリ上に作成されたファイルシステムであるため、物理ディスクよりも(はる)かに高速に読み書きを行えます。DavServerでも同様の効果を期待してしまいますが、残念ながらそういう訳には行きません。エクスプローラーがWebDAVサーバーへアクセスする際には「WebClient」というサービスを経由するようなのですが、このWebClientは、WebDAVサーバーからダウンロードしたファイルを一旦、物理ディスクにキャッシュしてから、これをエクスプローラーに引き渡すらしいのです。それが例えループバックデバイスであったとしてもそうします。つまり、RamBridgeのようにローカルメモリ上に存在するファイルでも、必ず物理ディスクにキャッシュしてからエクスプローラーに引き渡します。これでは、普通に物理ディスクからファイルを読み込む方が速いのです。

  6. URLを指定してファイルにアクセス。

    C#
    Uri url = new Uri(new Uri(server.Url), "test.txt");
    HttpClient client = new HttpClient();
    client.GetStringAsync(url).ContinueWith(t => Console.WriteLine(t.Result)).Wait();
    client.Dispose();

    WebDAVはHTTPを拡張して作られたプロトコルであるため、DavServerからファイルを取得するだけであれば、HTTPプロトコルでも十分機能します。GetStringAsyncメソッドがTaskオブジェクトを返すためプログラムが多少ややこしくなっていますが、URLで指定されたファイルを取得することができます。これは、Webブラウザでもファイルを取得できるということを意味します。

  7. DavServerを停止。

    C#
    server.Stop();

どうでしょうか。UNCやURLで何にでもアクセスできるというのは、以外に便利に感じたのではないでしょうか。ブリッジで接続できるデータソースは様々です。必ずしもディレクトリツリーである必要もありません。データベースやメールサーバーに強引に接続することも考えられます。可能性は感じますが、エクスプローラーでこれらを操作することがさほど便利だとも思えないため、この可能性は未知数です。試しに色々なブリッジを製作してみるのも良いかもしれません。