public async Task Run() { // Recipients are registered as always. var collection = new RecipientsCollection(); collection.Add <Foo>(); collection.Add <Bar>(); collection.Add <Baz>(); var aggregator = new Aggregator(collection); // The Send<TRequest> method checks only the input // parameter of the methods: AggregatedResponse <object?> all = await aggregator.Send(42); var allResults = all.AsResultsList(); // "42", 42L, 42 Console.WriteLine($"" + $"{allResults[0]} ({allResults[0]?.GetType().Name}), " + $"{allResults[1]} ({allResults[1]?.GetType().Name}), " + $"{allResults[2]} ({allResults[2]?.GetType().Name})"); // Instead the Send<TRequest, TResponse> method checks // also the return type of the methods, allowing to filter // on them and getting typed results: AggregatedResponse <string> onlyStrings = await aggregator.Send <string>(42); var onlyStringsResults = onlyStrings.AsResultsList(); // "42" Console.WriteLine($"{onlyStringsResults[0]} ({allResults[0]?.GetType().Name})"); }
public async Task Run() { var collection = new RecipientsCollection(); collection.Add <Foo>(); collection.Add <Bar>(); collection.Add <Baz>(); var aggregator = new Aggregator(collection); // The consumer can limit the duration of the aggregation by // providing a timeout (or CancellationToken) to the aggregator: // this will ensure that the response will be ready in // the given amount of time and will "discard" incomplete // (and also never-ending) invocations. var response = await aggregator.Send(42, TimeSpan.FromMilliseconds(50)); // The recipients that didn't complete in time will be // listed in the Incomplete property of the result: Console.WriteLine($"Completed {response.Completed.Count}"); Console.WriteLine( $"Incomplete {response.Incomplete.Count}: " + $"{response.Incomplete[0].Recipient.Type?.Name}, " + $"{response.Incomplete[1].Recipient.Type?.Name}"); }
public async Task Run() { var collection = new RecipientsCollection(); // Register typeless recipients using delegates. collection.Add((int n) => n.ToString()); collection.Add((int n) => n * 2); collection.Add((DateTime d) => d.Ticks); var aggregator = new Aggregator(collection); var responseOfInt = await aggregator.Send(42); var resultsOfInt = responseOfInt.AsResultsList(); // "42", 84 Console.WriteLine($"{resultsOfInt[0]}, {resultsOfInt[1]}"); var onlyStrings = await aggregator.Send <string>(42); var onlyStringResults = onlyStrings.AsResultsList(); // "42" Console.WriteLine($"{onlyStringResults[0]}"); var responseOfDateTime = await aggregator.Send(DateTime.UtcNow); var resultsOfDateTime = responseOfDateTime.AsResultsList(); // 'now.Ticks'L Console.WriteLine($"{resultsOfDateTime[0]}"); }
public async Task Run() { // Register the available recipients. var collection = new RecipientsCollection(); collection.Add <Foo>(); collection.Add <Bar>(); // Send a request and aggregate all the results. var aggregator = new Aggregator(collection); var response = await aggregator.Send(42); var results = response.AsResultsList(); // 1764L, 84 Console.WriteLine($"{results[0]}, {results[1]}"); }
public async Task Run() { var collection = new RecipientsCollection(); collection.Add <Foo>(); collection.Add <Bar>(); var aggregator = new Aggregator(collection); var response = await aggregator.Send("Don't Panic"); // The aggregated response separates the invocations // that completed successfully with a response and // the ones that failed with an exception. Console.WriteLine($"Completed {response.Completed.Count}"); Console.WriteLine( $"Faulted {response.Faulted.Count}: " + $"{response.Faulted[0].Recipient.Type?.Name} => " + $"{response.Faulted[0].Exception?.Message}"); }
public async Task Run() { var collection = new RecipientsCollection(); collection.Add <Foo>(); collection.Add <Bar>(); collection.Add <Baz>(); var aggregator = new Aggregator(collection); // It doesn't matter if a method returns // synchronously or asynchronously: // the aggregator awaits any async method // before aggregating the response. var response1 = await aggregator.Send(42); var results = response1.AsResultsList(); // 84L, 42L, "42" Console.WriteLine($"" + $"{results[0]} ({results[0]?.GetType().Name}), " + $"{results[1]} ({results[1]?.GetType().Name}), " + $"{results[2]} ({results[2]?.GetType().Name})"); // The aggregator provides a "all methods are async" abstraction // so that when using the Send<TRequest, TResponse> method // all the recipients that return either TResponse, Task<TResponse> // or ValueTask<TResponse> get invoked. var response2 = await aggregator.Send <long>(42); var longResults = response2.AsResultsList(); Console.WriteLine($"{longResults[0]} ({longResults[0].GetType().Name})"); Console.WriteLine($"{longResults[1]} ({longResults[1].GetType().Name})"); var response3 = await aggregator.Send <string>(42); var stringResults = response3.AsResultsList(); Console.WriteLine($"{stringResults[0]} ({stringResults[0].GetType().Name})"); }
public void Can_add_generic_type() { var id = _collection.Add <SomeType>(); Assert.NotEqual(default, id);