Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Validation section in README #27

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 101 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,116 @@ You can use C# 7 Tuples for more complex Types with multiple values:

### Validation

You can add validation to your Types by overriding the `protected void Validate() { } ` method:
There are two, independent ways to add validation to your Types. Both ways validate during Type creation.

#### Throw an exception during creation

You can add validation to your Types by overriding the `protected void Validate() { }` method to throw an exception when the type is created using `.From()`:

```
public class EmailAddress : ValueOf<string, EmailAddress>
{
protected override void Validate()
{
if (string.IsNullOrWhiteSpace(Value))
throw new ArgumentException("Value cannot be null or empty");
}
}

void Main()
{
// This will throw an ArgumentException
var myEmailAddress = EmailAddress.From("");
}
```

#### Return false while using an `out` argument

You may also implement validation to your Types by overriding the `protected bool TryValidate() { }` method to return `false`. This will cause the `TryFrom()` creation method to return false:

```
public class EmailAddress : ValueOf<string, EmailAddress>
{
protected override bool TryValidate()
{
if (string.IsNullOrWhitespace(Value))
return false;
}
}

void Main()
{
if (!EmailAddress.TryFrom("", out var myEmailAddress)
{
Console.WriteLine("Invalid email address");
}
}
```

#### Validation best practices

It is recommended to override both `Validate` and `TryValidate` with the same failure cases, if you choose to implement validation at all.

For example:

```
public class ValidatedClientRef : ValueOf<string, ValidatedClientRef>
public class EmailAddress : ValueOf<string, EmailAddress>
{
protected override void Validate()
{
if (!IsValidEmailAddress(Value))
throw new ArgumentException("Invalid email address");
}

protected override bool TryValidate()
{
return IsValidEmailAddress(Value);
}

// Prevent circular references from Validate and TryValidate by
// breaking out the logic into a separate method
public static bool IsValidEmailAddress(string value)
{
return !string.IsNullOrWhitespace(value)
}
}
```

If you prefer one method over the other, then consider at least overriding the alternative method to always fail. This will prevent someone from creating an invalid Type using the creation method you did not override.

For example:

```
public class EmailAddress : ValueOf<string, EmailAddress>
{
protected override void Validate()
{
throw new NotSupportedException("Use TryValidate() and TryFrom() instead");
}

protected override bool TryValidate()
{
return !string.IsNullOrWhitespace(Value)
}
}
```

or

```
public class EmailAddress : ValueOf<string, EmailAddress>
{
protected override void Validate()
{
if (string.IsNullOrWhiteSpace(Value))
throw new ArgumentException("Value cannot be null or empty");
}
}

protected override bool TryValidate()
{
return false; // Use Validate() and From() instead
}
}
```

## See Also
Expand Down