Skip to content

Commit

Permalink
Merge branch 'release/3.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
pascalberger committed Apr 29, 2020
2 parents 2377b2c + 9cc30b4 commit f14f713
Show file tree
Hide file tree
Showing 17 changed files with 288 additions and 24 deletions.
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# These owners will be the default owners for everything in the repo and
# will be requested for review when someone opens a pull request.
* @stefan-lindegger @Speeedy01 @marco-bertschi @pascalberger @christianbumann @x-jokay @silanosa @georgesgoetz
* @stefan-lindegger @Speeedy01 @marco-bertschi @pascalberger @christianbumann @eoehen @georgesgoetz
8 changes: 0 additions & 8 deletions .whitesource

This file was deleted.

2 changes: 1 addition & 1 deletion build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ https://cakebuild.net

[CmdletBinding()]
Param(
[string]$Script = "setup.cake",
[string]$Script = "recipe.cake",
[string]$Target = "Default",
[ValidateSet("Release", "Debug")]
[string]$Configuration = "Release",
Expand Down
48 changes: 46 additions & 2 deletions docs/input/docs/usage/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,49 @@ public class Data()
}
```

If a default value is needed, for example when specifying a file extension, the value can be encapsulated by a `Maybe` as well:

```csharp
public class Data()
{
public Data(Foo foo, Maybe<string> maybeFileExtension)
{
Foo = foo;
// If a file extension is specified the value from the Maybe is used
// If no value is provided by the Maybe the FileExtension is set to ".txt"
FileExtension = maybeFileExtension.ValueOrDefault(".txt");
}

public Foo { get; }
public string FileExtension { get; }
}
```

# Optional method arguments

Maybe can be declared as optional method arguments using the default keyword.

```csharp
/// maybeBar is an optional parameter. Maybe.None<Bar>() is default.
/// maybeBar is an optional parameter. Maybe.None<Bar>() is the default value.
public void Foo(Maybe<Bar> maybeBar = default)
{
maybeBar.Do(x => x.Bar());
}
```

It's also possible to retrieve the value (or a default value) from the `Maybe` in a method:

```csharp
private readonly defaultBar = new Bar();

/// maybeBar is an optional parameter. Maybe.None<Bar>() is the default value.
/// By using ValueOrDefault a default instance of the Bar class can be used.
public void Foo(Maybe<Bar> maybeBar = default)
{
var bar = maybeBar.ValueOrDefault(this.defaultBar);
}
```

# Projection method

Maybe provides a projection method (`Maybe<T>.Some<TResult>(Func<T, TResult>)`) with an argument of type Func<T, TResult>.
Expand All @@ -88,4 +119,17 @@ Maybe.Some(foo).Some(x => x.Bar).Do(x => ...);

Maybe.Some(foo) is the factory method call for the creation of the maybe of type Foo.
The second call Some(x => x.Bar) is the projection method projecting the Foo maybe to a maybe of its property type Bar.
Therefore projections of cascades of properties can be done without the need of null checks or null propagation.
Therefore projections of cascades of properties can be done without the need of null checks or null propagation.

# Assertion

A `Maybe` can be asserted to have a value by calling `ValueOrException`:

```csharp
/// maybeBar may or may not have a value.
public void Foo(Maybe<Bar> maybeBar)
{
// If maybeBar doesn't have a value an exception is thrown.
var bar = maybeBar.ValueOrException(nameof(maybeBar));
}
```
4 changes: 2 additions & 2 deletions nuspec/nuget/BBT.MaybePattern.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
<summary>An option type for .NET.</summary>
<description>An option type for .NET.</description>
<license type="expression">MIT</license>
<projectUrl>https://github.com/bbtsoftware/BBT.Maybe/</projectUrl>
<projectUrl>https://bbtsoftware.github.io/BBT.Maybe/</projectUrl>
<icon>icon.png</icon>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<repository type="git" url="https://github.com/bbtsoftware/BBT.Maybe.git"/>
<copyright>Copyright © BBT Software AG</copyright>
<tags>Maybe Functional</tags>
<releaseNotes>https://github.com/bbtsoftware/BBT.Maybe/releases/tag/3.0.0</releaseNotes>
<releaseNotes>https://github.com/bbtsoftware/BBT.Maybe/releases/tag/3.1.0</releaseNotes>
</metadata>
<files>
<file src="..\..\..\..\nuspec\nuget\icon.png" target="" />
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion src/BBT.MaybePattern.Tests/BBT.MaybePattern.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
<PackageReference Include="Shouldly" Version="4.0.0-beta0002" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
Expand Down
53 changes: 53 additions & 0 deletions src/BBT.MaybePattern.Tests/MaybeIntTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
namespace BBT.MaybePattern.Tests
{
using BBT.MaybePattern;
using BBT.MaybePattern.Tests.TestData;
using Shouldly;
using Xunit;

public sealed class MaybeIntTests
{
public sealed class SerializeAndDeserialize
{
/// <summary>
/// Serialize and deserialize a maybe of int.
/// </summary>
[Fact]
public void Should_Work_For_None()
{
// Arrange
var maybe = Maybe.None<object>();
var testData = new TestDataClass() { Maybe = maybe };

// Act & Assert
using (var stream = TestUtils.SerializeToStream(testData))
{
var testDataDeserialized = (TestDataClass)TestUtils.DeserializeFromStream(stream);

testDataDeserialized.Maybe.ShouldBeOfType<Maybe<object>>();
testDataDeserialized.Maybe.HasValue.ShouldBeFalse();
}
}

/// <summary>
/// Serialize and deserialize a maybe of int.
/// </summary>
[Fact]
public void Should_Work_For_Some()
{
// Arrange
var maybe = Maybe.Some<object>(new object());
var testData = new TestDataClass() { Maybe = maybe };

// Act & Assert
using (var stream = TestUtils.SerializeToStream(testData))
{
var testDataDeserialized = (TestDataClass)TestUtils.DeserializeFromStream(stream);

testDataDeserialized.Maybe.ShouldBeOfType<Maybe<object>>();
testDataDeserialized.Maybe.HasValue.ShouldBeTrue();
}
}
}
}
}
53 changes: 53 additions & 0 deletions src/BBT.MaybePattern.Tests/MaybeStructIntTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
namespace BBT.MaybePattern.Tests
{
using BBT.MaybePattern;
using BBT.MaybePattern.Tests.TestData;
using Shouldly;
using Xunit;

public sealed class MaybeStructIntTests
{
public sealed class SerializeAndDeserialize
{
/// <summary>
/// Serialize and deserialize a maybe of int.
/// </summary>
[Fact]
public void Should_Work_For_None()
{
// Arrange
var maybeStruct = Maybe.NoneStruct<int>();
var testData = new TestDataStruct() { MaybeStruct = maybeStruct };

// Act & Assert
using (var stream = TestUtils.SerializeToStream(testData))
{
var testDataDeserialized = (TestDataStruct)TestUtils.DeserializeFromStream(stream);

testDataDeserialized.MaybeStruct.ShouldBeOfType<MaybeStruct<int>>();
testDataDeserialized.MaybeStruct.HasValue.ShouldBeFalse();
}
}

/// <summary>
/// Serialize and deserialize a maybe of int.
/// </summary>
[Fact]
public void Should_Work_For_Some()
{
// Arrange
var maybeStruct = Maybe.SomeStruct<int>(5);
var testData = new TestDataStruct() { MaybeStruct = maybeStruct };

// Act & Assert
using (var stream = TestUtils.SerializeToStream(testData))
{
var testDataDeserialized = (TestDataStruct)TestUtils.DeserializeFromStream(stream);

testDataDeserialized.MaybeStruct.ShouldBeOfType<MaybeStruct<int>>();
testDataDeserialized.MaybeStruct.HasValue.ShouldBeTrue();
}
}
}
}
}
16 changes: 15 additions & 1 deletion src/BBT.MaybePattern.Tests/MaybeStructTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,21 @@ public void Should_Return_Value_If_Called_For_Some_Mabye()
public sealed class TheValueOrExceptionMethod
{
[Fact]
public void Should_Throw_InvalidOperationException_If_Called_For_None_Mabye()
public void Should_Throw_InvalidOperationException_With_TypeName_If_Called_Without_Args_For_None_Mabye()
{
// Arrange
var maybeNone = Maybe.NoneStruct<BaseStruct>();

// Act
var exception = Record.Exception(() => maybeNone.ValueOrException());

// Assert
exception.ShouldBeOfType<InvalidOperationException>();
exception.Message.ShouldContain(nameof(BaseStruct));
}

[Fact]
public void Should_Throw_InvalidOperationException_If_Called_With_Args_For_None_Mabye()
{
// Arrange
var maybeNone = Maybe.NoneStruct<BaseStruct>();
Expand Down
16 changes: 15 additions & 1 deletion src/BBT.MaybePattern.Tests/MaybeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,21 @@ public void Should_Return_Value_If_Called_For_Some_Mabye()
public sealed class TheValueOrExceptionMethod
{
[Fact]
public void Should_Throw_InvalidOperationException_If_Called_For_None_Mabye()
public void Should_Throw_InvalidOperationException_With_TypeName_If_Called_Without_Args_For_None_Mabye()
{
// Arrange
var maybeNone = Maybe.None<BaseClass>();

// Act
var exception = Record.Exception(() => maybeNone.ValueOrException());

// Assert
exception.ShouldBeOfType<InvalidOperationException>();
exception.Message.ShouldContain(nameof(BaseClass));
}

[Fact]
public void Should_Throw_InvalidOperationException_If_Called_With_Args_For_None_Mabye()
{
// Arrange
var maybeNone = Maybe.None<BaseClass>();
Expand Down
16 changes: 16 additions & 0 deletions src/BBT.MaybePattern.Tests/TestData/TestDataClass.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace BBT.MaybePattern.Tests.TestData
{
using System;

/// <summary>
/// Used for test purposes.
/// </summary>
[Serializable]
public class TestDataClass
{
/// <summary>
/// Gets or sets the maybe.
/// </summary>
public Maybe<object> Maybe { get; set; }
}
}
16 changes: 16 additions & 0 deletions src/BBT.MaybePattern.Tests/TestData/TestDataStruct.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace BBT.MaybePattern.Tests.TestData
{
using System;

/// <summary>
/// Used for test purposes.
/// </summary>
[Serializable]
public class TestDataStruct
{
/// <summary>
/// Gets or sets the maybe.
/// </summary>
public MaybeStruct<int> MaybeStruct { get; set; }
}
}
50 changes: 50 additions & 0 deletions src/BBT.MaybePattern.Tests/TestUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
namespace BBT.MaybePattern.Tests
{
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

/// <summary>
/// Provides utility method for test purposes.
/// </summary>
public class TestUtils
{
/// <summary>
/// Serializes the given object into memory stream.
/// </summary>
/// <param name="objectType">the object to be serialized.</param>
/// <returns>The serialized object as memory stream.</returns>
public static MemoryStream SerializeToStream(object objectType)
{
var stream = new MemoryStream();
try
{
var lFormatter = new BinaryFormatter();
lFormatter.Serialize(stream, objectType);
return stream;
}
catch
{
if (stream != null)
{
stream.Dispose();
}
}

throw new InvalidOperationException();
}

/// <summary>
/// Deserializes as an object.
/// </summary>
/// <param name="stream">the stream to deserialize.</param>
/// <returns>the deserialized object.</returns>
public static object DeserializeFromStream(MemoryStream stream)
{
var formatter = new BinaryFormatter();
stream.Seek(0, SeekOrigin.Begin);
var objectType = formatter.Deserialize(stream);
return objectType;
}
}
}
4 changes: 2 additions & 2 deletions src/BBT.MaybePattern/BBT.MaybePattern.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8">
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.0.0">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="SauceControl.InheritDoc" Version="0.4.0">
<PackageReference Include="SauceControl.InheritDoc" Version="1.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
10 changes: 8 additions & 2 deletions src/BBT.MaybePattern/Maybe.cs
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,16 @@ public T ValueOrDefault(
/// <param name="additionalMessage">Additional error message.</param>
/// <returns>The value.</returns>
public T ValueOrException(
string maybeParameterName,
string maybeParameterName = "",
string additionalMessage = "")
{
return MaybeUtils.CheckParameterNotNull(this.value, maybeParameterName, additionalMessage);
var parameterName = maybeParameterName;
if (string.IsNullOrEmpty(maybeParameterName))
{
parameterName = typeof(T).Name;
}

return MaybeUtils.CheckParameterNotNull(this.value, parameterName, additionalMessage);
}

/// <inheritdoc/>
Expand Down
Loading

0 comments on commit f14f713

Please sign in to comment.