JollyQuotes provides a simple, class-oriented interface for quick and painless access to multiple quote generation APIs scattered all across the Internet.
This package supports .NET 5 or greater.
Currently, JollyQuotes provides access to the following APIs:
If you have any suggestions regarding additional API support, feel free to ask or create your own push request!
Every JollyQuotes API package consists of 4 main classes:
- [api-name]Service - offers access to all actions defined by the target web API.
- [api-name]QuoteGenerator - generates quotes using actions available in the [api-name]Service class.
- [api-name]Quote - a model that contains data about the quote, such as its author, source, date.
- [api-name]Resources - provides links to important resources of the target web API, such as the api page, documentation, GitHub.
Some packages provide more functionality, such as converters or additional models.
To wire up a custom or unsupported API with JollyQuotes, you need to do the following:
-
Download this NuGet package.
-
Create a quote model (preferably a record) named [api-name]Quote and implement the JollyQuotes.IQuote interface.
Note: There are two built-in implementations of this interface: JollyQuotes.Quote and JollyQuotes.QuoteWithId, so you can feel free to either inherit from them or use them directly instead of creating a new model.
Example:
public record TestQuote : IQuote { public int Id { get; init; } public string Value { get; init; } public string Author { get; init; } public string Source { get; init; } public DateTime? Date { get; init; } public string[] Tags { get; init; } }
-
Create a static class named [api-name]Resources and containing important links and resources about the API you are implementing, such as api page or documentation.
Example:
public static class TestResources { public const string ApiPage = "http://api.test.com"; public const string GitHub = "https://github.com//abc/Test"; }
-
Create a class named [api-name]Service that defines all actions that can be performed using the API being implemented.
Note: It is recommended to implement the JollyQuotes.IQuoteService interface or inherit the JollyQuotes.QuoteService class for better clarity and testability.
Note: It is recommended for all publicly-visible methods of the service to return System.Threading.Tasks.Task or System.Threading.Tasks.Task<T> instead of direct types.
Note: It is recommended to also create an interface to allow mocking.
Example:
public interface ITestService : IQuoteService { Task<TestQuote> GetRandomQuote(); Task<TestQuote> GetRandomQuote(string tag); } public class TestService : ITestService { public IResourceResolver Resolver { get; } public TestService(IResourceResolver resolver) { Resolver = resolver; } public Task<TestQuote> GetRandomQuote() { return Resolver.ResolveAsync<TestQuote>($"{TestResources.ApiPage}/randomQuote"); } public Task<TestQuote> GetRandomQuote(string tag) { return Resolver.ResolveAsync<TestQuote>($"{TestResources.ApiPage}/randomQuote/{tag}"); } }
-
Create a class named [api-name]QuoteGenerator that generates quotes on demand, preferably by using a [api-name]Service. There are multiple ways to achieve that, but by far the easiest and the least painful is to inherit one of the following pre-built abstract classes:
-
JollyQuotes.QuoteGenerator - basic implementation of the JollyQuotes.IQuoteGenerator interface; does not provide any additional features.
-
JollyQuotes.QuoteResolver - provides a JollyQuotes.IResourceResolver and implements the System.IDisposable interface.
-
JollyQuotes.QuoteClient - good choice for web-based APIs; provides a System.Net.Http.HttpClient and a JollyQuotes.HttpResolver; implements the System.IDisposable interface.
-
JollyQuotes.EnumerableQuoteGenerator - basic implementation of the JollyQuotes.IQuoteGenerator interface; implements the System.Collections.Generic.IEnumerable<T> interface.
-
JollyQuotes.EnumerableQuoteResolver - provides a JollyQuotes.IResourceResolver and implements the System.Collections.Generic.IEnumerable<T> and System.IDisposable interfaces.
-
JollyQuotes.EnumerableQuoteClient - good choice for web-based APIs; provides a System.Net.Http.HttpClient and a JollyQuotes.HttpResolver; implements the System.Collections.Generic.IEnumerable<T> and System.IDisposable interfaces.
Example:
public class TestQuoteGenerator : QuoteClient<TestQuote> { public ITestService Service { get; } public TestQuoteGenerator(ITestService service) : base(service.Resolver) { Service = service; } public override TestQuote GetRandomQuote() { return Service.GetRandomQuote().Result; } public override TestQuote? GetRandomQuote(string tag) { return Service.GetRandomQuote(tag).Result; } public override TestQuote? GetRandomQuote(string[]? tags) { if (tags is null || tags.Length == 0) { return GetRandomQuote(); } foreach (string tag in tags) { if (GetRandomQuote(tag) is TestQuote quote) { return quote; } } } }
Note: Generator classes listed above do not support caching of the generated quotes, meaning calls to their methods will in majority cases result in a call to one of System.Net.Http.HttpClient's methods. To avoid that issue, each of said classes provides a second implementation of itself with support for caching, in form of an inner class named WithCache.
Be aware that the WithCache version has slightly different method signatures, so make sure whether you want support caching before you actually write the generator.
public class TestQuoteGenerator : QuoteClient<TestQuote>.WithCache { public ITestService Service { get; } public TestQuoteGenerator(ITestService service) : base(service.Resolver) { Service = service; } protected override TestQuote DownloadRandomQuote() { return Service.GetRandomQuote().Result; } protected override TestQuote? DownloadRandomQuote(string tag) { return Service.GetRandomQuote(tag).Result; } protected override TestQuote? DownloadRandomQuote(string[]? tags) { if (tags is null || tags.Length == 0) { return DownloadRandomQuote(); } foreach (string tag in tags) { if (DownloadRandomQuote(tag) is TestQuote quote) { return quote; } } } }
Congratulations, you just wired up a new API with JollyQuotes! If you think your code is ready to be shared and you want it to be published under JollyQuote's branding, feel free to make a push request.
-