@@ -42,6 +42,33 @@ Observable.Interval(TimeSpan.FromSeconds(1))
4242<sup ><a href =' https://github.com/hardkoded/ReactiveExtensions-Sharp/blob/main/test/RxSharp.Tests/Samples/QuickTasteSample.cs#L19-L27 ' title =' Snippet source file ' >snippet source</a > | <a href =' #snippet-quick-taste-csharp ' title =' Start of snippet ' >anchor</a ></sup >
4343<!-- endSnippet -->
4444
45+ ## What about ` pipe ` ?
46+
47+ RxJS's ` pipe(op1, op2, op3) ` is mostly just method chaining wearing a different hat — ` source.Map(...).Filter(...) `
48+ above * is* the translation. But RxJS's ` pipe() ` has a second job: called on its own (not as an ` Observable `
49+ method), it builds a ** reusable** transformation out of several operators, so you can define it once and apply
50+ it to multiple streams. RxSharp covers that with ` OperatorFunction<TSource, TResult> ` + ` Pipe ` :
51+
52+ <!-- snippet: pipe-csharp -->
53+ <a id =' snippet-pipe-csharp ' ></a >
54+ ``` cs
55+ public static void Run (Observable < int > numbersA , Observable < int > numbersB )
56+ {
57+ // A reusable transformation, defined once - the equivalent of RxJS's standalone
58+ // `const squareAndFilterEven = pipe(map(x => x * x), filter(x => x % 2 === 0));`
59+ OperatorFunction < int , int > squareAndFilterEven = source => source .Map (x => x * x ).Filter (x => x % 2 == 0 );
60+
61+ numbersA .Pipe (squareAndFilterEven ).Subscribe (x => Console .WriteLine (x ));
62+ numbersB .Pipe (squareAndFilterEven ).Subscribe (x => Console .WriteLine (x ));
63+ }
64+ ```
65+ <sup ><a href =' https://github.com/hardkoded/ReactiveExtensions-Sharp/blob/main/test/RxSharp.Tests/Samples/PipeSample.cs#L11-L21 ' title =' Snippet source file ' >snippet source</a > | <a href =' #snippet-pipe-csharp ' title =' Start of snippet ' >anchor</a ></sup >
66+ <!-- endSnippet -->
67+
68+ There's no hand-written 9-arity ` pipe(op1, op2, ..., op9) ` overload set, deliberately — it exists in RxJS mainly
69+ to work around JS not having method chaining with generics the way C# does. ` Pipe ` here only takes a single,
70+ already-composed ` OperatorFunction ` ; build that function with ordinary chaining, same as everywhere else.
71+
4572## The example that started this project
4673
4774[ Puppeteer] ( https://pptr.dev/ ) (the JS browser-automation library) builds its ` Locator.click() ` /` .fill() ` actions
@@ -68,11 +95,6 @@ public static async Task<string> FindElementOnceItRendersAsync(Func<Task<string>
6895<sup ><a href =' https://github.com/hardkoded/ReactiveExtensions-Sharp/blob/main/test/RxSharp.Tests/Samples/RetryUntilTimeoutSample.cs#L13-L21 ' title =' Snippet source file ' >snippet source</a > | <a href =' #snippet-retry-until-timeout-csharp ' title =' Start of snippet ' >anchor</a ></sup >
6996<!-- endSnippet -->
7097
71- One line instead of a hand-rolled state machine — same retry-until-success-or-timeout-or-cancel behavior. See
72- [ ` handoff/puppeteer-sharp-integration.md ` ] ( handoff/puppeteer-sharp-integration.md ) for the actual before/after
73- against puppeteer-sharp's real current ` Locator ` code, and how the rest of its rxjs-based internals
74- (` waitForNetworkIdle ` , ` ScreenRecorder ` ) map onto RxSharp.
75-
7698## Install
7799
78100```
0 commit comments