FluentDefense 1.0.0-preview6
See the version list below for details.
dotnet add package FluentDefense --version 1.0.0-preview6
NuGet\Install-Package FluentDefense -Version 1.0.0-preview6
<PackageReference Include="FluentDefense" Version="1.0.0-preview6" />
paket add FluentDefense --version 1.0.0-preview6
#r "nuget: FluentDefense, 1.0.0-preview6"
// Install FluentDefense as a Cake Addin #addin nuget:?package=FluentDefense&version=1.0.0-preview6&prerelease // Install FluentDefense as a Cake Tool #tool nuget:?package=FluentDefense&version=1.0.0-preview6&prerelease
Defensive Extensions
A library that makes defensive programming easier.
Goals briefly:
- Zero dependency
- Extensible
- Developer Friendly
NOT Goals
- High performance (low cpu/memory)
What is defensive programming?
"Defensive programming is about protecting yourself from being hurt by something dangerous (If bad data is sent to a routine, it will not hurt the routine). By writing code that will protect yourself from bad data, unexpected events, and other programmers mistakes, will in most case reduce bugs and create a high quality software. Good programmers will not let bad data through. It’s important to validate input parameters to not let the garbage in. It’s also important to make sure that if garbage does come in, noting will goes out or an exception will be thrown. "
Getting Started
- Install the FluentDefense package https://www.nuget.org/packages/FluentDefense
- Include the using statement for the defensive extensions:
using FluentDefense
A note about compatibility
Note that this library is only supported on dotnet 6+ and will likely not be backward compatible in newer versions. If you would like multitargeting, you may contribute or request backward compat from me. Since this is a hobby project, I cannot realistically support production usage besides my own. You may easily stick with older versions of the library, or upgrade your own projects for compatibility with newer dotnet versions.
Example Code
public void EnableAuthentication(string tokenBaseUrl, string clientId, string clientSecret, string appName)
{
_tokenBaseUrl = tokenBaseUrl;
tokenBaseUrl
.Defend()
.ValidUri()
.Throw(); // throw an exception if any of the validations fail
clientId
.Defend("client id") // you can also specify the argument name
.NotNullOrEmpty()
.ErrorMessage; // Get a single string newline seperated list of errors.
var errors = clientSecret
.Defend()
.NotNullOrEmpty()
.Errors; // get a list of errors
appName
.Defend()
.NotNullOrEmpty()
.Throw();
_tokenAuthenticationCredentials = new TokenAuthenticationCredentials
{
AppName = appName,
ClientId = clientId,
ClientSecret = clientSecret
};
}
Extending Fluent Defense
You can easily add to an existing defender using the Custom()
method.
public static class TestIntDefenderExtensions
{
public static IntDefender IsEven(this IntDefender defender)
{
defender.Custom(value => value % 2 == 0, (value, name) => $"{value} for {name} is not even");
return defender;
}
}
You can then use it as you would use the defender normally, and mix it in with existing defensive actions.
itemId.Defend()
.NotZero()
.NotNegative()
.IsEven() // chain your custom extension easily
.Custom(i => i.ToString().Length == 5, (_, _) => "Order ids must be five digits")
.Throw();
Building Defenders for your own types
You can easily create a new defender for your own custom types in two simple steps.
- Create a defender subclass
public class PersonDefender : DefenderBase<PersonDefender, Person>
{
public PersonDefender(string parameterName, Person value) : base(parameterName, value)
{
}
// create a method for the defender, returning itself back to the caller
public PersonDefender HasValidName()
{
if (Value.Name?.Length < 2)
{
// add any errors you need
AddError($"'{Value.Name}' is not a valid name for person '{ParameterName}'. Name must have at least two characters and not be null");
}
return this;
}
public PersonDefender HasValidAge()
{
if (!Value.Age.Defend().InRange(1, 120).IsValid)
{
AddError($"'{Value.Age}' is not a valid age for person '{ParameterName}'. Age must be between 1 and 120 years");
}
return this;
}
// you can create composite calls for common use cases
public PersonDefender HasEnoughInfoProvided() => HasValidName().HasValidAge();
}
- Create an extension method that extends the object with a Defend() method.
public static class PersonDefenderExtensions
{
public static PersonDefender Defend(this Person person, [CallerArgumentExpression("person")] string parameterName = "")
=> new(parameterName, person);
}
- Use the new extension for validation!
var applicant = new Person();
applicant.Defend()
.HasEnoughInfoProvided()
.Throw();
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net6.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
2.0.0 | 36,097 | 8/13/2022 |
1.0.0-preview6 | 173 | 3/23/2022 |
1.0.0-preview4 | 164 | 3/23/2022 |
Release