Skip to content

Commit

Permalink
Updated readme
Browse files Browse the repository at this point in the history
  • Loading branch information
PawelGerr committed Mar 5, 2023
1 parent 5548e9e commit 45e1915
Showing 1 changed file with 104 additions and 8 deletions.
112 changes: 104 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,32 +222,128 @@ Features:
* Roslyn Analyzers and CodeFixes help the developers to implement the Value Objects correctly
* Allows custom properties and methods
* Provides appropriate factory methods for creation of new value objects based on the specified properties/fields
* Allows custom validation of [constructor](https://github.com/PawelGerr/Thinktecture.Runtime.Extensions/wiki/Value-Objects#validation-of-the-constructor-arguments) and [factory method](https://github.com/PawelGerr/Thinktecture.Runtime.Extensions/wiki/Value-Objects#validation-of-the-factory-method-arguments) arguments
* Allows custom [validation](https://github.com/PawelGerr/Thinktecture.Runtime.Extensions/wiki/Value-Objects#validation) of [constructor](https://github.com/PawelGerr/Thinktecture.Runtime.Extensions/wiki/Value-Objects#validation-of-the-constructor-arguments) and [factory method](https://github.com/PawelGerr/Thinktecture.Runtime.Extensions/wiki/Value-Objects#validation-of-the-factory-method-arguments) arguments
* Additional features for [simple Value Objects (1 "key"-property/field)](https://github.com/PawelGerr/Thinktecture.Runtime.Extensions/wiki/Value-Objects#simple-value-objects) and [complex Value Objects (2 properties/fields or more)](https://github.com/PawelGerr/Thinktecture.Runtime.Extensions/wiki/Value-Objects#complex-value-objects)
* Simple Value Objects: allows cast and type conversion from key-type to Value Object and vice versa
* Simple Value Objects: provides an implementation of `IComparable<T>` if the key-property/field is an `IComparable<T>` or has an `IComparer<T>`
* Simple Value Objects: provides an implementation of `IFormattable` if the key-property/field is an `IFormattable`
* Provides proper implementation of `Equals`, `GetHashCode`, `ToString` and equality comparison via `==` and `!=`
* [Allows custom equality comparison](https://github.com/PawelGerr/Thinktecture.Runtime.Extensions/wiki/Value-Objects#custom-comparer)
* Provides implementation of `IComparable`, `IComparable<T>`, `IFormattable`, `IParsable<T>` and comparison operators `<`, `<=`, `>`, `>=`
* [Allows custom equality comparison](https://github.com/PawelGerr/Thinktecture.Runtime.Extensions/wiki/Value-Objects#custom-comparer) and [custom comparer](https://github.com/PawelGerr/Thinktecture.Runtime.Extensions/wiki/Value-Objects#custom-comparer)
* Handling of [null](https://github.com/PawelGerr/Thinktecture.Runtime.Extensions/wiki/Value-Objects#null-in-factory-methods-yields-null) and [empty strings](https://github.com/PawelGerr/Thinktecture.Runtime.Extensions/wiki/Value-Objects#empty-string-in-factory-methods-yields-null)
* [JSON support](https://github.com/PawelGerr/Thinktecture.Runtime.Extensions/wiki/Value-Objects#json-serialization) (`System.Text.Json` and `Newtonsoft.Json`)
* [ASP.NET Core support](https://github.com/PawelGerr/Thinktecture.Runtime.Extensions/wiki/Value-Objects#support-for-aspnet-core-model-binding) (model binding and model validation)
* [Support for Minimal Web Api Parameter Binding and ASP.NET Core Model Binding](https://github.com/PawelGerr/Thinktecture.Runtime.Extensions/wiki/Value-Objects#support-for-minimal-web-api-parameter-binding-and-aspnet-core-model-binding)
* [Entity Framework Core support](https://github.com/PawelGerr/Thinktecture.Runtime.Extensions/wiki/Value-Objects#support-for-entity-framework-core) (`ValueConverter`)
* [MessagePack support](https://github.com/PawelGerr/Thinktecture.Runtime.Extensions/wiki/Value-Objects#messagepack-serialization) (`IMessagePackFormatter`)

Definition of a value object with 1 custom property `Value`. All other features mentioned above are generated by the [Roslyn Source Generators](https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview) in the background.
## Simple Value Object

Definition of 2 value objects, one with 1 `string` property `Value` and the other with an `int`.

```C#
[ValueObject]
public partial class ProductName
public sealed partial class ProductName
{
public string Value { get; }
}

// The member can be a private readoly field as well
//private readonly string _value;
[ValueObject]
public sealed partial class Amount
{
private readonly int _value;
}
```

After the implementation of the `ProductName`, a Roslyn source generator kicks in and implements the rest. Following API is available from now on.

```C#
// Factory method for creation of new instances.
// Throws ValidationException if the validation fails
ProductName bread = ProductName.Create("Bread");

// Alternatively, using an explicit cast (behaves the same as with Create)
ProductName bread = (ProductName)"Bread"; // is the same as calling "ProductName.Create"
-----------

// the same as above but returns a bool instead of throwing an exception (dictionary-style)
bool created = ProductName.TryCreate("Milk", out ProductName milk);

-----------

// similar to TryCreate but returns a ValidationResult instead of a boolean.
ValidationResult? validationResult = ProductName.Validate("Milk", out var milk);

if (validationResult == ValidationResult.Success)
{
logger.Information("Product name {Name} created", milk);
}
else
{
logger.Warning("Failed to create product name. Validation result: {ValidationResult}", validationResult.ErrorMessage);
}

-----------

// implicit conversion to the type of the key member
string valueOfTheProductName = bread; // "Bread"
-----------

// Equality comparison with 'Equals'
// which compares the key members using default or custom 'IEqualityComparer<T>'
bool equal = bread.Equals(bread);

-----------

// Equality comparison with '==' and '!='
bool equal = bread == bread;
bool notEqual = bread != bread;

-----------

// Hash code
int hashCode = bread.GetHashCode();

-----------

// 'ToString' implementation
string value = bread.ToString(); // "Bread"
------------

// Implements IParsable<T> which is especially helpful with minimal web apis.
// This feature can be disabled if it doesn't make sense (see ValueObjectAttribute).
bool success = ProductName.TryParse("New product name", null, out var productName);

------------

// Implements "IFormattable" if the key member is an "IFormattable".
// This feature can be disabled if it doesn't make sense (see ValueObjectAttribute).
var amount = Amount.Create(42);
string formattedValue = amount.ToString("000", CultureInfo.InvariantCulture); // "042"
------------

// Implements "IComparable<ProductName>" if the key member is an "IComparable"
// This feature can be disabled if it doesn't make sense (see ValueObjectAttribute).
var amount = Amount.Create(1);
var otherAmount = Amount.Create(2);

var comparison = amount.CompareTo(otherAmount); // -1
// Implements comparison operators (<,<=,>,>=) if the key member has comparison operators itself.
// This feature can be disabled if it doesn't make sense (see ValueObjectAttribute).
var isBigger = amount > otherAmount;

------------

// Implements addition / subtraction / multiplication / division if the key member supports operators
// This feature can be disabled if it doesn't make sense (see ValueObjectAttribute).
var sum = amount + otherAmount;
```

## Complex Value Object

Definition of a complex value object with 2 properties and a custom validation of the arguments.

```C#
Expand Down

0 comments on commit 45e1915

Please sign in to comment.