Getting Started
To use this source generator include it as a source only dependency in your project.
<ItemGroup>
<PackageReference Include="Tuxedo.SourceGenerator" Version="x.x.x">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
Now we can build our first refined type.
Let's create a password string that must comply with some simple rules.
It must,
- Be at least 8 characters long
- Contain at least 1 uppercase letter
- Contain at least 1 number
- Contain at least 1 special character
To do this create a simple predicate method, It helps to do this on the partial struct that will eventually be the refined type.
So in this case that type will be called a PasswordString
, it looks like this,
/// <summary>
/// A valid password string
/// </summary>
public readonly partial struct PasswordString
{
// this is the definition of what makes a password string valid.
// the name of the method combined with the type it operates on make up the name of the refined type
// in this case PasswordString
[Tuxedo.Refinement(
"The string must be at least 8 characters long, contain at most 1 uppercase letter, number and special character. You provided '{value}'.",
Name = nameof(PasswordString)
)]
private static bool IsValidPassword(string value)
{
if (value.Length < 8)
{
return false;
}
var hasUppercaseLetter = false;
var hasNumber = false;
var hasSpecialCharacter = false;
foreach (var @char in value)
{
hasUppercaseLetter |= char.IsUpper(@char);
hasNumber |= char.IsDigit(@char);
hasSpecialCharacter |= !char.IsLetterOrDigit(@char) && !char.IsWhiteSpace(@char);
}
return hasUppercaseLetter && hasNumber && hasSpecialCharacter;
}
}
Which can be used like this,
bool isValid = PasswordString.TryParse("12Da3%sd", out var password, out _);
Assert.True(isValid);
Assert.Equal("12Da3%sd", password.Value);