2012-05-26 19 views
0

我是Reactive Extension初學者。 Gideon Engelberth在我的問題中給了我很好的關於Reactive Extension的答案。如何將IObservable <Unit>返回值分配給XDocument實例

How to convert img url to BASE64 string in HTML on one method chain by using LINQ or Rx

現在我有怎樣的IObservable返回值分配給的XDocument實例的第二個問題。

吉迪恩給了我以下樣品。

public IObservable<Unit> ReplaceImageLinks(XDocument document) 
    { 
     return (from element in GetImages(document) 
       let address = new Uri(element.Attribute("src").Value) 
       select (from data in DownloadAsync(address) 
         select Convert.ToBase64String(data) 
         ).Do(base64 => element.Attribute("src").Value = base64) 
       ).Merge() 
       .IgnoreElements() 
       .Select(s => Unit.Default); 
    } 

我想這樣做。芽這似乎很難...

public void Convert(XDocument input, out XDocument output) 
{ 
    output = ReplaceImageLinks(input); 
} 

回答

0

所以你在這裏只是一半有用。看來基甸已經回答了你的問題,但是,也許不知道你的額外要求。所以我假設你需要一個XDoc,將所有的Image src屬性從一個路徑轉換爲路徑所代表的BASE64。然後您想要在完成所有處理後返回新的XDoc對象。正確?

如果是這樣的話,那麼你可以這樣做。

public IObservable<XDocument> ReplaceImageLinks(XDocument document) 
{ 
    return Observable.Create<XDocument>(o=> 
    { 
     try{ 
      var images = document.Descendants("Image"); 
      Parallel.ForEach(images, SwapUriForContent); 
      o.OnNext(document); 
      o.OnCompleted(); 
     } 
     catch(Exception ex) 
     { 
      o.OnError(ex); 
     } 
     return Disposable.Empty; //Should really be a handle to Parallel.ForEach cancellation token. 
    }); 
} 

private static void SwapUriForContent(XElement imageElement) 
{ 
    var address = new Uri(imageElement.Attribute("src").Value, UriKind.RelativeOrAbsolute); 
    imageElement.Attribute("src").Value = Download(address); 
} 

public static string Download(Uri input) 
{ 
    //TODO Replace with real implemenation 
    return input.ToString().ToUpper(); 
} 

我剛剛與

string str = 
    @"<?xml version=""1.0""?> 
    <!-- comment at the root level --> 
    <Root> 
     <Child>Content</Child> 
     <Image src=""image.jpg""/> 
     <Child> 
      <Image src=""image2.jpg""/> 
     </Child> 
    </Root>"; 
XDocument doc = XDocument.Parse(str); 
ReplaceImageLinks2(doc).Dump(); 

然而測試,有事情不對的。第一,我們正在改變狀態。在處理併發時,這不是一個好的開始。我們真的應該返回一個具有正確值的新XDoc。第二,這似乎比Rx更多的是TPL問題。 Rx最適合處理傳入數據的流式傳輸,因此您需要執行並行處理。我認爲一個更好的選擇就是完成任務。

public Task<XDocument> ReplaceImageLinks3(XDocument source) 
{ 
    return Task.Factory.StartNew(()=> 
    { 
     var copy = new XDocument(source); 
     var images = copy.Descendants("Image"); 
     Parallel.ForEach(images, SwapUriForContent); 
     return copy; 
    }); 
} 

見拙作When to Use Rx的一節IntroToRx.com

相關問題