Last active
November 15, 2019 09:09
-
-
Save stijnmoreels/634d98ac2e63e59041f77e6b3a980b2d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Author | |
{ | |
private readonly string _name; | |
private Author(string name) { _name = name; } | |
public static ValidationResult<Author> Create(string author) | |
{ | |
const string name = @"[A-Z]{1}[a-z]*\.?"; | |
string pattern = $@"^({name})( {name})*$"; | |
return Spec.Of<string>() | |
.NotNullOrWhiteSpace("author name should not be blank") | |
.Add(s => s.Length > 1, "author name should at least be a single character") | |
.Matches(pattern, $"author name should match regular expression: {pattern}") | |
.CreateModel(author, validated => new Author(validated)); | |
} | |
} | |
public class ISBN13 | |
{ | |
private readonly string _code; | |
private ISBN13(string code) { _code = code; } | |
public static ValidationResult<ISBN13> Create(string code) | |
{ | |
const string pattern = "^[0-9]+$"; | |
return Spec.Of<string>() | |
.NotNullOrWhiteSpace("ISBN13 number should not be blank") | |
.Add(s => s.Length == 13, "ISBN13 number should be 13 characters long") | |
.Matches(pattern, $"ISBN13 number should match regular expression: {pattern}") | |
.StartsWith("978", "ISBN13 number should start with '978'") | |
.Add(Checksum, "ISBN13 checksum was invalid") | |
.CreateModel(code, validated => new ISBN13(validated)); | |
} | |
private static bool Checksum(string code) | |
{ | |
IEnumerable<int> numbers = | |
code.ToCharArray() | |
.Select(c => Int32.Parse(c.ToString())); | |
int sumNumbers = | |
numbers.Take(12) | |
.Select((n, i) => i % 2 != 0 ? n * 3 : n) | |
.Sum(); | |
int remaining = sumNumbers % 10; | |
int checksum = remaining != 0 ? 10 - remaining : remaining; | |
int lastNumber = numbers.Last(); | |
return checksum == lastNumber; | |
} | |
} | |
public class Int1000 | |
{ | |
private readonly int _value; | |
private Int1000(int value) { _value = value; } | |
public static ValidationResult<Int1000> Create(int value) | |
{ | |
return Spec.Of<int>() | |
.InclusiveBetween(1, 1000, "integer number must be between 1-1000") | |
.CreateModel(value, validated => new Int1000(validated)); | |
} | |
} | |
public class Book | |
{ | |
private readonly Author _author; | |
private readonly ISBN13 _isbn13; | |
private readonly Int1000 _pages; | |
private Book(Author author, ISBN13 isbn13, Int1000 pages) | |
{ | |
_author = author; | |
_isbn13 = isbn13; | |
_pages = pages; | |
} | |
public static ValidationResult<Book> Create(string author, string isbn13, int pages) | |
{ | |
ValidationResult<Author> authorResult = Author.Create(author); | |
ValidationResult<ISBN13> isbn13Result = ISBN13.Create(isbn13); | |
ValidationResult<Int1000> pagesResult = Int1000.Create(pages); | |
return ValidationResult.Combine(authorResult, isbn13Result, pagesResult, (auth, isbn, ps) => new Book(auth, isbn, ps)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment