2013-08-23 27 views
0

我已經爲C#Stream編寫了一個包裝類,因爲我希望它能夠將數據注入到流中並在通過ReadAsync()讀取數據時調用函數。然而,「注入」部分不起作用,我不知道爲什麼。爲什麼我的Inject方法不向流中注入數據?

class ExtendedStream : Stream 
{ 
    private readonly Stream _originalStream; 
    private readonly Action<byte[]> _readCallback; 

    private ManualResetEvent dataInjected = new ManualResetEvent(false); 
    private List<byte> data = new List<byte>(); 
    private int pos = 0; 

    public ExtendedStream(Stream originalStream, Action<byte[]> readCallback) 
    { 
     _originalStream = originalStream; 
     _readCallback = readCallback; 
    } 

    public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) 
    { 
     var read = await _originalStream.ReadAsync(buffer, offset, count, cancellationToken); 

     _readCallback(buffer); 

     return read; 
    } 

    public void Inject(string text) 
    { 
     data.AddRange(new UTF8Encoding(false).GetBytes(text)); 
     dataInjected.Set(); 
    } 

    private IEnumerable<byte> GetBytes(int count) 
    { 
     int returned = 0; 

     while (returned == 0) 
     { 
      if (pos < data.Count) 
      { 
       while (pos < data.Count && returned < count) 
       { 
        yield return data[pos]; 

        pos += 1; returned += 1; 
       } 
      } 
      else 
      { 
       dataInjected.Reset(); 
       dataInjected.WaitOne(); 
      } 
     } 
    }  

    public override int Read(byte[] buffer, int offset, int count) 
    { 
     var bytes = GetBytes(count).ToArray(); 

     for (int i = 0; offset + i < buffer.Length && i < bytes.Length; i++) 
     { 
      buffer[offset + i] = bytes[i]; 
     } 

     return bytes.Length; 
    } 

    public override void Write(byte[] buffer, int offset, int count) 
    { 
     _originalStream.Write(buffer, offset, count); 
    } 

    public override bool CanRead 
    { 
     get { return _originalStream.CanRead; } 
    } 

    public override bool CanSeek 
    { 
     get { return _originalStream.CanSeek; } 
    } 

    public override bool CanWrite 
    { 
     get { return _originalStream.CanWrite; } 
    } 

    public override void Flush() 
    { 
     _originalStream.Flush(); 
    } 

    public override long Length 
    { 
     get { return _originalStream.Length; } 
    } 

    public override long Position 
    { 
     get { return _originalStream.Position; } 
     set { _originalStream.Position = value; } 
    } 

    public override long Seek(long offset, SeekOrigin origin) 
    { 
     return _originalStream.Seek(offset, origin); 
    } 

    public override void SetLength(long value) 
    { 
     _originalStream.SetLength(value); 
    }   
} 

然後我正在用XmlReader讀取流如下。

using (XmlReader xmlReader = XmlReader.Create(_extendedStream, new XmlReaderSettings() { Async = true })) 
{ 
       while (await xmlReader.ReadAsync()) 
       {       
        switch (xmlReader.NodeType) 
        {        
         case XmlNodeType.EndElement: 
          if (xmlReader.LocalName.Equals("test")) 
          { 
           _log.Debug("</test> injected!");        
          } 
          break; 
         default:        
          break; 
        } 
} 

如果我打電話給_extendedStream.Inject("</test>"),數據永遠不會被注入。有誰知道爲什麼?

+1

您的'ReadAsync'方法委託給'_originalStream.ReadAsync',所以我不認爲您的示例代碼會調用您重寫的'Read'方法(注入魔法發生的地方)。你是否嘗試過使用調試器? –

+0

姆姆......是的,我確實通過調試器完成了代碼。我認爲(不要問我爲什麼),'ReadAsync'使用'Read',就像http://stackoverflow.com/questions/12015279/disposing-of-xmlreader-with-pending-async -讀。我如何重寫'ReadAsync'(一個例子會超級)? –

回答

0

您的ReadAsync方法代表_originalStream.ReadAsync,所以我不認爲您的示例代碼中調用了覆蓋的Read方法(其中注入魔法發生)。

而不是覆蓋ReadAsync(可能很複雜),您可以將原始數據流的讀取移動到你的Read方法,這將通過異步基地ReadAsync方法被調用。

// UNTESTED CODE, MAY CONTAIN OFF BY ONE ERRORS 
public override int Read(byte[] buffer, int offset, int count) 
{ 
    int totalBytesRead = 0; 
    var bytes = GetBytes(count).ToArray(); 

    // write injected bytes into buffer 
    for (int i = 0; offset + i < buffer.Length && i < bytes.Length; i++) 
    { 
     buffer[offset + i] = bytes[i]; 
    } 

    if(bytes.Length < count) 
    { 
     // we reached the end of the custom bytes, so read the rest from the original stream 
     count = count - bytes.Length; 
     offset += bytes.Length; 
     totalBytesRead = _originalStream.Read(buffer, offset, count); 
    } 

    totalBytesRead += bytes.Length; 

    _readCallback(buffer); 

    return totalBytesRead; 
} 

這可能需要一些調整,以防止被注入了一遍又一遍你插入的數據,但至少注入邏輯將運行。

相關問題