Skip to content

Commit d95bc94

Browse files
committed
readme
1 parent 34a9012 commit d95bc94

File tree

1 file changed

+120
-31
lines changed

1 file changed

+120
-31
lines changed

README.md

+120-31
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55
Danom is a C# library that provides (monadic) structures to facilitate durable programming patterns in C# using [Option](#option) and [Result](#result).
66

77
## Key Features
8-
- Implementation of common monads like [Option](#option), [Result](#result), and [ResultOption](#resultoption).
8+
9+
- Implementation of common monads: [Option](#option) and [Result](#result).
10+
- Exhaustive matching to prevent null reference exceptions.
911
- Fluent API for chaining operations.
10-
- [Error handling](#using-results) with monads.
11-
- Support for asynchronous operations.
1212
- Integrated with [ASP.NET Core](#aspnet-core-mvc-integration) and [Fluent Validation](#fluent-validation-integration).
13+
- API for [parsing strings](#string-parsing) into .NET primitives and value types.
14+
- Supports asynchronous operations.
1315

1416
## Design Goals
17+
1518
- Easy to use API for common monadic operations.
1619
- Efficient implementation to minimize overhead.
1720
- Seamless integration with existing C# code and libraries.
@@ -213,53 +216,139 @@ var resultErrorsTyped =
213216
Result<int>.Error(new ResultErrors("error-key", "An error occurred"));
214217
```
215218

216-
## ResultOption
219+
## String Parsing
217220

218-
Represents a combination of the Result and Option monads. This is useful when you want to handle both the success and failure of an operation, but also want to handle the case where a value might not exist. It simplifies the inspection by eliminating the redundant nested `Match` calls.
221+
Most applications will at some point need to parse strings into primitives and value types. This is especially true when working with external data sources.
219222

220-
### Creating ResultOptions
223+
`Option` provides a natural mechanism to handle the case where the string cannot be parsed. The "TryParse" API is provided to simplify the process of parsing strings into .NET primitives and value types.
221224

222225
```csharp
223-
var resultOption = ResultOption<int, string>.Ok(5);
224-
225-
// or, with an error
226-
var resultOptionError = ResultOption<int, string>.Error("An error occurred");
227-
228-
// or, with no value
229-
var resultOptionNone = ResultOption<int, string>.None();
230-
```
226+
using Danom;
231227

232-
### Using ResultOptions
228+
// a common pattern
229+
var x = int.TryParse("123", out var y) ? Option<int>.Some(y) : Option<int>.None();
233230

234-
ResultOptions are commonly used when an operation might not succeed, but also where a value might not exist. For example:
231+
// or, more using the TryParse API
232+
var myInt = intOption.TryParse("123"); // -> Some(123)
233+
var myDouble = doubleOption.TryParse("123.45"); // -> Some(123.45)
234+
var myBool = boolOption.TryParse("true"); // -> Some(true)
235235
236-
```csharp
237-
public Option<int> LookupUserId(string username) => // ...
236+
// if the string cannot be parsed
237+
var myIntNone = intOption.TryParse("danom"); // -> None
238+
var myDoubleNone = doubleOption.TryParse("danom"); // -> None
239+
var myBoolNone = boolOption.TryParse("danom"); // -> None
238240
239-
public ResultOption<int, string> GetUserId(string username)
240-
{
241-
if(username == "admin")
242-
{
243-
return ResultOption<int,string>.Error("Invalid username");
244-
}
241+
// null strings are treated as None
242+
var myIntNull = intOption.TryParse(null); // -> None
243+
```
245244

246-
return LookupUserId(username).Match(
247-
some: id => ResultOption<int, string>.Ok(1) :
248-
none: ResultOption<int, string>.None);
245+
The full API is below:
249246

250-
// or, using the extension method
251-
// return LookupUserId(username).ToResultOption();
252-
}
247+
```csharp
248+
public static class boolOption {
249+
public static Option<bool> TryParse(string? x); }
250+
251+
public static class byteOption {
252+
public static Option<byte> TryParse(string? x, IFormatProvider? provider = null); }
253+
254+
public static class shortOption {
255+
public static Option<short> TryParse(string? x, IFormatProvider? provider = null);
256+
public static Option<short> TryParse(string? x); }
257+
258+
public static class intOption {
259+
public static Option<int> TryParse(string? x, IFormatProvider? provider = null);
260+
public static Option<int> TryParse(string? x); }
261+
262+
public static class longOption {
263+
public static Option<long> TryParse(string? x, IFormatProvider? provider = null);
264+
public static Option<long> TryParse(string? x); }
265+
266+
public static class decimalOption {
267+
public static Option<decimal> TryParse(string? x, IFormatProvider? provider = null);
268+
public static Option<decimal> TryParse(string? x); }
269+
270+
public static class doubleOption {
271+
public static Option<double> TryParse(string? x, IFormatProvider? provider = null);
272+
public static Option<double> TryParse(string? x); }
273+
274+
public static class floatOption {
275+
public static Option<float> TryParse(string? x, IFormatProvider? provider = null);
276+
public static Option<float> TryParse(string? x); }
277+
278+
public static class GuidOption {
279+
public static Option<Guid> TryParse(string? x, IFormatProvider? provider = null);
280+
public static Option<Guid> TryParse(string? x);
281+
public static Option<Guid> TryParseExact(string? x, string? format); }
282+
283+
public static class DateTimeOffsetOption {
284+
public static Option<DateTimeOffset> TryParse(string? x, IFormatProvider? provider = null);
285+
public static Option<DateTimeOffset> TryParse(string? x);
286+
public static Option<DateTimeOffset> TryParseExact(string? x, string? format, IFormatProvider? provider = null, DateTimeStyles dateTimeStyles = DateTimeStyles.None); }
287+
288+
public static class DateTimeOption {
289+
public static Option<DateTime> TryParse(string? x, IFormatProvider? provider = null);
290+
public static Option<DateTime> TryParse(string? x);
291+
public static Option<DateTime> TryParseExact(string? x, string? format, IFormatProvider? provider = null, DateTimeStyles dateTimeStyles = DateTimeStyles.None); }
292+
293+
public static class DateOnlyOption {
294+
public static Option<DateOnly> TryParse(string? x, IFormatProvider? provider = null);
295+
public static Option<DateOnly> TryParse(string? x);
296+
public static Option<DateOnly> TryParseExact(string? x, string? format, IFormatProvider? provider = null, DateTimeStyles dateTimeStyles = DateTimeStyles.None); }
297+
298+
public static class TimeOnlyOption {
299+
public static Option<TimeOnly> TryParse(string? x, IFormatProvider? provider = null);
300+
public static Option<TimeOnly> TryParse(string? x);
301+
public static Option<TimeOnly> TryParseExact(string? x, string? format, IFormatProvider? provider = null, DateTimeStyles dateTimeStyles = DateTimeStyles.None); }
302+
303+
public static class TimeSpanOption {
304+
public static Option<TimeSpan> TryParse(string? x, IFormatProvider? provider = null);
305+
public static Option<TimeSpan> TryParse(string? x);
306+
public static Option<TimeSpan> TryParseExact(string? x, string? format, IFormatProvider? provider = null); }
307+
308+
public static class EnumOption {
309+
public static Option<TEnum> TryParse<TEnum>(string? x) where TEnum : struct; }
253310
```
254311

255312
## Integrations
256313

257-
Since Danom introduces types that are most commonly found in your model and business logic layers, external integrations are not only inevitable but required to provide a seamless experience when build applications.
314+
Since Danom introduces types that are most commonly found in your model and business logic layers, external integrations are not only inevitable but required to provide a seamless experience when building applications.
258315

259316
### Fluent Validation Integration
260317

261318
Danom is integrated with [Fluent Validation](https://fluentvalidation.net/) to provide a seamless way to validate your models and return a `Result` or `ResultOption` with the validation errors.
262319

320+
A quick example:
321+
322+
```csharp
323+
using Danom;
324+
using Danom.Validation;
325+
using FluentValidation;
326+
327+
public record Person(
328+
string Name,
329+
Option<string> Email);
330+
331+
public class PersonValidator
332+
: AbstractValidator<Person>
333+
{
334+
public PersonValidator()
335+
{
336+
RuleFor(x => x.Name).NotEmpty();
337+
RuleFor(x => x.Email).Optional(x => x.EmailAddress());
338+
}
339+
}
340+
341+
var result =
342+
ValidationResult<Person>
343+
.From<PersonValidator>(new(
344+
Name: "John Doe",
345+
Email: Option.Some("[email protected]")));
346+
347+
result.Match(
348+
x => Console.WriteLine("Input is valid: {0}", x),
349+
e => Console.WriteLine("Input is invalid: {0}", e));
350+
```
351+
263352
Documentation can be found [here](src/Danom.Validation/README.md).
264353

265354
### ASP.NET Core MVC Integration

0 commit comments

Comments
 (0)