0

特定のファイル形式を読み取るアプリケーションがあります。さらに、アプリケーションは、代替ファイル形式を読み取り、ツールがネイティブにサポートする標準化された形式に変換する「プラグイン」をサポートします。

次のようなインターフェイスを定義したいと思います。

/// <summary>
/// Interface for file transformer. Implementers of this interface provide a means to
/// convert a given file into Foo Format.
/// </summary>
public interface IFileTransformerPlugin
{
    /// <summary>Gets the name of the transformer to display to the user.</summary>
    /// <value>The name of the transformer displayed to the user.</value>
    string DisplayName
    {
        get;
    }

    /// <summary>Determines if this transformer can handle the given format.</summary>
    /// <remarks>
    /// This method should return very quickly; reading only a small portion of the
    /// input stream. This method is intended to be a rough cut check -- returning true
    /// does not necessarily mean that the file will parse successfully on full load.
    /// </remarks>
    /// <param name="fileContents">The file contents.</param>
    /// <returns>
    /// true if this transformer can handle the supplied format, false otherwise.
    /// </returns>
    bool CanHandleLogFormat(Stream fileContents);

    /// <summary>Transforms a file into Foo Format.</summary>
    /// <param name="inputFile">The input log stream.</param>
    /// <param name="outputFile">The output log stream (where the output should be
    /// written).</param>
    /// <returns>A transformation result which includes error information.</returns>
    LogTransformationResult Transform(Stream inputFile, Stream outputFile);
}

問題は、ストリームを取得する変換メソッドに起因します。概念的には、プラグインではなくプラグインホストにこれらのストリームを「所有」させ、IDisposeまたはこれらのストリーム上のあらゆるものを呼び出す責任を負わせたいと思います。たとえば、テストシナリオでは、呼び出し元がMemoryStreamを出力として渡して、出力が有効であることを確認できると便利です。

ただし、プラグインの作成者として、フレームワークで上位レベルのフォーマット構造を使用できることが望ましいです。つまり、TextReader / TextWriter; XmlTextReader / XmlTextWriter; ただし、これらのクラスは、基になるストリームの所有権を取得し、ストリームを提供するコードが何をするかに関係なく、基になるストリームでDisposeを呼び出します。(少なくとも、それらのクラス自体が正しく配置されていると仮定します)

この問題を回避するために、このインターフェイスをどのように作り直すことができますか?それも解決可能な問題ですか?

4

3 に答える 3

3

これにより、従来のソフトウェアエンジニアリングラインが呼び出されます。「すべての問題は、追加レベルの間接参照で解決できます」。ストリームをラップして、ベースストリームに委任するワンライナーメソッドを提供するだけです。Disposeメソッドを除いて、クライアントコードが何を実行しても、ストリームの制御を維持できるように何もしません。好き:

public class OwnedStream : Stream {
    private Stream stream;
    public OwnedStream(Stream stream) { this.stream = stream; }
    protected override void Dispose(bool disposing) {
        // Do nothing
    }
    public override bool CanRead { get { return stream.CanRead; } }

    // etcetera, just delegate to "stream"
}

そのメダルの反対側に注意してください。他のコードへの参照を渡しています。それはそれを保存することができます、あなたは彼らがそれをいつ使い終えたかわからないでしょう。

于 2012-08-30T00:30:36.133 に答える
1

リーダー/ライターを閉じるとストリームが閉じるのが好きではありませんでした(まさにあなたが説明した理由で)。私は通常、ストリームではなくリーダー/ライターを渡すことでこれを回避します。通常、ストリームの形式(テキストとバイナリ)を制御する必要があり、XmlTextReader/Writerは提供されたTextReader/Writerからインスタンス化できるため、プラグインにバイナリまたはテキストアクセサーを指定するかどうかを決定するだけです。 。

于 2012-08-29T23:41:47.753 に答える
0

インターフェイスのゲッターを介してストリームオブジェクトにアクセスできるようにしてみませんか?そうすれば、アプリケーションは必要なときにいつでも実装からストリーム参照を取得できます。

public interface IFileTransformerPlugin {
  string DisplayName { get; }
  string Stream inputFile { get; }

  // etc.
}
于 2012-08-29T23:34:57.487 に答える