Skip to content

Commit

Permalink
Updated readme and added an example makrdown file for EntityFramework…
Browse files Browse the repository at this point in the history
…Core Value Converters
  • Loading branch information
Temo Nikolaishvili committed Jun 18, 2024
1 parent 43fb16e commit 9abfc75
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<Product>Domain Primitives</Product>
<Company>ALTA Software llc.</Company>
<Copyright>Copyright © 2024 ALTA Software llc.</Copyright>
<Version>4.0.0</Version>
<Version>4.1.0</Version>
</PropertyGroup>

<PropertyGroup>
Expand Down
126 changes: 126 additions & 0 deletions EntityFrameworkCoreExample.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@

# Generating EntityFrameworkCore Value Converters

1. In the `.csproj` file where **AltaSoft.DomainPrimitives.Generator** is located, add the following item:

```xml
<PropertyGroup>
<DomainPrimitiveGenerator_GenerateEntityFrameworkCoreValueConverters>true</DomainPrimitiveGenerator_GenerateEntityFrameworkCoreValueConverters>
</PropertyGroup>
```

**Note:** Ensure EntityFrameworkCore is added in the references.

After this, ValueConverters for each DomainPrimitive will be generated.

## Example
Given a domain primitive `AsciiString`:

```csharp
/// <summary>
/// A domain primitive type representing an ASCII string.
/// </summary>
/// <remarks>
/// The AsciiString ensures that its value contains only ASCII characters.
/// </remarks>
public partial class AsciiString : IDomainValue<string>
{
/// <inheritdoc/>
public static PrimitiveValidationResult Validate(string value)
{
var input = value.AsSpan();

// ReSharper disable once ForCanBeConvertedToForeach
for (var i = 0; i < input.Length; i++)
{
if (!char.IsAscii(input[i]))
return "value contains non-ascii characters";
}

return PrimitiveValidationResult.Ok;
}
}
```

The following converter will be generated:

```csharp
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by 'AltaSoft DomainPrimitives Generator'.
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
#nullable enable

using AltaSoft.DomainPrimitives.XmlDataTypes;
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using AltaSoft.DomainPrimitives;

namespace AltaSoft.DomainPrimitives.XmlDataTypes.EntityFrameworkCore.Converters;

/// <summary>
/// ValueConverter for <see cref="AsciiString"/>
/// </summary>
public sealed class AsciiStringValueConverter : ValueConverter<AsciiString, string>
{
/// <summary>
/// Constructor to create AsciiStringValueConverter
/// </summary>
public AsciiStringValueConverter() : base(v => v, v => v)
{
}
}
```

**Note:** All Domain Primitives have implicit conversion to/from their primitive type. Therefore, no explicit conversion is required.

## Helper Extension Method

A helper extension method is also generated to add domain primitive conversions globally to `ModelConfigurationBuilder`:

```csharp
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by 'AltaSoft DomainPrimitives Generator'.
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
#nullable enable

using AltaSoft.DomainPrimitives.XmlDataTypes;
using Microsoft.EntityFrameworkCore;
using AltaSoft.DomainPrimitives.XmlDataTypes.EntityFrameworkCore.Converters;

namespace AltaSoft.DomainPrimitives.XmlDataTypes.Converters.Extensions;

/// <summary>
/// Helper class providing methods to configure EntityFrameworkCore ValueConverters for DomainPrimitive types of AltaSoft.DomainPrimitives.XmlDataTypes
/// </summary>
public static class ModelConfigurationBuilderExt
{
/// <summary>
/// Adds EntityFrameworkCore ValueConverters for specific custom types to ensure proper mapping to EFCore ORM.
/// </summary>
/// <param name="configurationBuilder">The ModelConfigurationBuilder instance to which converters are added.</param>
public static ModelConfigurationBuilder AddDomainPrimitivePropertyConversions(this ModelConfigurationBuilder configurationBuilder)
{
configurationBuilder.Properties<AsciiString>().HaveConversion<AsciiStringValueConverter>();
configurationBuilder.Properties<GDay>().HaveConversion<GDayValueConverter>();
configurationBuilder.Properties<GMonth>().HaveConversion<GMonthValueConverter>();
configurationBuilder.Properties<GMonthDay>().HaveConversion<GMonthDayValueConverter>();
configurationBuilder.Properties<GYear>().HaveConversion<GYearValueConverter>();
configurationBuilder.Properties<GYearMonth>().HaveConversion<GYearMonthValueConverter>();
configurationBuilder.Properties<NegativeInteger>().HaveConversion<NegativeIntegerValueConverter>();
configurationBuilder.Properties<NonEmptyString>().HaveConversion<NonEmptyStringValueConverter>();
configurationBuilder.Properties<NonNegativeInteger>().HaveConversion<NonNegativeIntegerValueConverter>();
configurationBuilder.Properties<NonPositiveInteger>().HaveConversion<NonPositiveIntegerValueConverter>();
configurationBuilder.Properties<PositiveInteger>().HaveConversion<PositiveIntegerValueConverter>();
return configurationBuilder;
}
}
```
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ The **AltaSoft.DomainPrimitives.Generator** offers a diverse set of features:
* **NumberType Operations:** Automatically generates basic arithmetic and comparison operators, by implementing Static abstract interfaces. [More details regarding numeric types](#number-types-attribute)
* **IParsable Implementation:** Automatically generates parsing for non-string types.
* **XML Serialiaziton** Generates IXmlSerializable interface implementation, to serialize and deserialize from/to xml.
* **EntityFrameworkCore ValueConverters** Facilitates seamless integration with EntityFrameworkCore by using ValueConverters to treat the primitive type as its underlying type. For more details, refer to [EntityFrameworkCore ValueConverters](EntityFrameworkCoreExample.md)

## Supported Underlying types
1. `string`
Expand Down

0 comments on commit 9abfc75

Please sign in to comment.