Skip to content

Commit

Permalink
Next (#162)
Browse files Browse the repository at this point in the history
* Fixes #159, Only supports netstandard2.0 and netstandard2.1

* Fixes #161

* Changes EnsureOptions to be readonly

* Change so that Ensure.That returns the Param

* NuGet upgrades

* Fixes benchmark

* Docs
  • Loading branch information
danielwertheim authored Oct 18, 2021
1 parent 0273546 commit 87adc5e
Show file tree
Hide file tree
Showing 36 changed files with 1,000 additions and 459 deletions.
69 changes: 60 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,88 @@
# Ensure.That
Ensure.That is a simple guard clause argument validation lib, that helps you with validation of your arguments.

It's developed for .NET 4.5.1 as well as .NET Standard 1.1, 2.0, and 2.1 available via [NuGet](https://www.nuget.org/packages/ensure.that/).
It's developed for .NET Standard 2.0 and 2.1 available via [NuGet](https://www.nuget.org/packages/ensure.that/).

[![Build Status](https://dev.azure.com/daniel-wertheim/os/_apis/build/status/Ensure.That-CI?branchName=master)](https://dev.azure.com/daniel-wertheim/os/_build/latest?definitionId=1&branchName=master)
[![NuGet](https://img.shields.io/nuget/v/ensure.that.svg)](http://nuget.org/packages/ensure.that)

## Using extension methods
This was supposed to be removed but after some wishes from the community it has been kept it with some slight changes.

If you are worried that the constructed `public struct Param<T> {}` created for the argument being validated will hurt your performance you can use any of the other constructs e.g. contextual `Ensure.String` or `EnsureArg`.

```csharp
Ensure.That(myString).IsNotNullOrWhiteSpace();
Ensure.That(myString, nameof(myArg)).IsNotNullOrWhiteSpace();
Ensure.That(myString, nameof(myArg), opts => opts.WithMessage("Foo")).IsNotNullOrWhiteSpace();
Ensure.That(myString, nameof(myArg), (in EnsureOptions opts) => opts.WithMessage("Foo")).IsNotNullOrWhiteSpace();
```

Chainable:

```csharp
Ensure
.That(myString)
.IsNotNullOrWhiteSpace()
.IsGuid();
```

Easily extendable:

```csharp
public static class StringArgExtensions
{
public static StringParam IsNotFishy(this StringParam param)
=> param.Value != "fishy"
? param
: throw Ensure.ExceptionFactory.ArgumentException("Something is fishy!", param.Name);
}

Ensure.That(myString, nameof(myString)).IsNotFishy();
```

**NOTE:** If you are worried that the constructed `public readonly struct Param<T> {}` created for the argument being validated will hurt your performance you can use any of the other constructs e.g. contextual `Ensure.String` or `EnsureArg` (see below for samples).

## Using contextual validation
This flavour was introduced in the `v7.0.0` release.
Introduced in the `v7.0.0` release.

```csharp
Ensure.String.IsNotNullOrWhiteSpace(myString);
Ensure.String.IsNotNullOrWhiteSpace(myString, nameof(myArg));
Ensure.String.IsNotNullOrWhiteSpace(myString, nameof(myArg), opts => opts.WithMessage("Foo"));
Ensure.String.IsNotNullOrWhiteSpace(myString, nameof(myArg), (in EnsureOptions opts) => opts.WithMessage("Foo"));
```

Easily extendable:

```csharp
public static class StringArgExtensions
{
public static string IsNotFishy(this StringArg _, string value, string paramName = null)
=> value != "fishy"
? value
: throw Ensure.ExceptionFactory.ArgumentException("Something is fishy!", paramName);
}

Ensure.String.IsNotFishy(myString, nameof(myString));
```

### Using static simple methods
The `EnsureArg` flavour was added in the `v5.0.0` release.
Introduced in the `v5.0.0` release.

```csharp
EnsureArg.IsNotNullOrWhiteSpace(myString);
EnsureArg.IsNotNullOrWhiteSpace(myString, nameof(myArg));
EnsureArg.IsNotNullOrWhiteSpace(myString, nameof(myArg), opts => opts.WithMessage("Foo"));
EnsureArg.IsNotNullOrWhiteSpace(myString, nameof(myArg), (in EnsureOptions opts) => opts.WithMessage("Foo"));
```

Easily extendable:

```csharp
public static partial class EnsureArg
{
public static string IsNotFishy(string value, string paramName = null)
=> value != "fishy"
? value
: throw Ensure.ExceptionFactory.ArgumentException("Something is fishy!", paramName);
}

EnsureArg.IsNotFishy(myString, nameof(myString));
```

## Samples
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ name: $(SemVer)

variables:
BuildConfiguration: Release
BuildRev: $[counter(format('{0:yyyyMMdd}', pipeline.startTime), 1)]
SemVer: $[ variables['Build.SourceBranchName'] ]
CommitId: $(Build.SourceVersion)

Expand All @@ -15,8 +14,8 @@ trigger:
pr: none

pool:
vmImage: windows-2019
vmImage: ubuntu-latest

stages:
- template: azure-templates/stage-build.yml
- template: azure-templates/stage-deploy.yml
- template: stage-build.yml
- template: stage-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pr:
- master

pool:
vmImage: windows-2019
vmImage: ubuntu-latest

stages:
- template: azure-templates/stage-build.yml
- template: stage-build.yml
18 changes: 5 additions & 13 deletions azure-templates/stage-build.yml → azure-devops/stage-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,40 +13,32 @@ stages:
projects: 'src/*.sln'
arguments: '-c $(BuildConfiguration) --no-incremental --nologo -p:TreatWarningsAsErrors=true -p:Version=$(SemVer) -p:InformationalVersion=$(CommitId)'

- task: DotNetCoreCLI@2
displayName: 'UnitTests .Net4.5.2'
inputs:
command: test
projects: 'src/Tests/**/UnitTests.csproj'
arguments: '-c $(BuildConfiguration) -f net452 --no-build'
testRunTitle: 'UnitTests .Net4.5.2'

- task: DotNetCoreCLI@2
displayName: 'UnitTests .NetCoreApp3.1'
inputs:
command: test
projects: 'src/Tests/**/UnitTests.csproj'
projects: 'src/**/UnitTests.csproj'
arguments: '-c $(BuildConfiguration) -f netcoreapp3.1 --no-build'
testRunTitle: 'UnitTests .NetCoreApp3.1'

- task: DotNetCoreCLI@2
displayName: 'UnitTests .Net5'
inputs:
command: test
projects: 'src/Tests/**/UnitTests.csproj'
projects: 'src/**/UnitTests.csproj'
arguments: '-c $(BuildConfiguration) -f net5.0 --no-build'
testRunTitle: 'UnitTests .Net5'

- task: DotNetCoreCLI@2
displayName: 'Pack Nupkg'
inputs:
command: custom
custom: pack
projects: 'src/*.sln'
arguments: '-c $(BuildConfiguration) --no-build -o $(Build.ArtifactStagingDirectory) -p:Version=$(SemVer) -p:InformationalVersion=$(CommitId)'

- task: PublishPipelineArtifact@1
displayName: 'Publish Artifacts'
inputs:
path: '$(Build.ArtifactStagingDirectory)'
artifact: Artifacts
artifact: Artifacts
File renamed without changes.
37 changes: 2 additions & 35 deletions src/projects/EnsureThat/Annotations/JetBrains.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. */

using System;
using System.Diagnostics.CodeAnalysis;

#pragma warning disable 1591
// ReSharper disable UnusedMember.Global
Expand All @@ -44,40 +45,6 @@ internal sealed class RegexPatternAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Parameter)]
internal sealed class NoEnumerationAttribute : Attribute { }

/// <summary>
/// Indicates that the value of the marked element could never be <c>null</c>.
/// </summary>
/// <example><code>
/// [NotNull] object Foo() {
/// return null; // Warning: Possible 'null' assignment
/// }
/// </code></example>
[AttributeUsage(
AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property |
AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event |
AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)]
internal sealed class NotNullAttribute : Attribute { }

/// <summary>
/// Indicates that a method does not make any observable state changes.
/// The same as <c>System.Diagnostics.Contracts.PureAttribute</c>.
/// </summary>
/// <example><code>
/// [Pure] int Multiply(int x, int y) => x * y;
///
/// void M() {
/// Multiply(123, 42); // Waring: Return value of pure method is not used
/// }
/// </code></example>
/// <remarks>
/// <c>System.Diagnostics.Contracts.PureAttribute</c> is not available for NETSTANDARD1_1.
/// For consistency, using this version of the attribute for all profiles rather than
/// just NETSTANDARD1_1.
/// </remarks>
[AttributeUsage(AttributeTargets.Method)]
internal sealed class PureAttribute : Attribute { }


/// <summary>
/// Indicates that the function argument should be string literal and match one
/// of the parameters of the caller function. For example, ReSharper annotates
Expand Down Expand Up @@ -129,7 +96,7 @@ internal sealed class InvokerParameterNameAttribute : Attribute { }
/// // A method that returns null if the parameter is null,
/// // and not null if the parameter is not null
/// [ContractAnnotation("null =&gt; null; notnull =&gt; notnull")]
/// public object Transform(object data)
/// public object Transform(object data)
/// </code></item>
/// <item><code>
/// [ContractAnnotation("=&gt; true, result: notnull; =&gt; false, result: null")]
Expand Down
2 changes: 1 addition & 1 deletion src/projects/EnsureThat/Annotations/NotNullAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace System.Diagnostics.CodeAnalysis
{
/// <summary>
/// This is JUST so we can avoid having #if regions in each usage site.
///
///
/// For non-supported frameworks, it may be ignored by CodeAnalysis, but allows the usage
/// sites to avoid all having
/// <code>
Expand Down
12 changes: 12 additions & 0 deletions src/projects/EnsureThat/Enforcers/AnyArg.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ public T HasValue<T>([NoEnumeration, ValidatedNotNull, NotNull] T value, [Invoke
return value;
}

/// <summary>
/// Ensures value is not null.
/// Supports both <see cref="Nullable{T}"/> and reference types.
/// If you know you are dealing with a certain type, e.g struct use preferred <see cref="IsNotNull{T}(T?, string, OptsFn)"/>
/// overload instead as it is more performant.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <param name="paramName"></param>
/// <param name="optsFn"></param>
/// <returns></returns>
/// <remarks>If you know you are dealing with e.g. a struct, the <see cref="IsNotNull{T}(T?, string, OptsFn)"/> overload is more performant.</remarks>
[return: NotNull]
[ContractAnnotation("value:null => halt")]
public T IsNotNull<T>([NoEnumeration, ValidatedNotNull, NotNull] T value, [InvokerParameterName] string paramName = null, OptsFn optsFn = null) where T : class
Expand Down
Loading

0 comments on commit 87adc5e

Please sign in to comment.