namespace Shop;
partial class Order : DDDToolkit.BaseTypes.AggregateRoot<Shop.OrderId>
{
protected Order()
{
}
partial void CheckInvariants();
private static readonly DDDToolkit.Invariants.IInvariant<Shop.Order>[] __invariants =
[
new Shop.Order.MustHaveLines(),
];
private void CollectInvariantViolations(
ref System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>? violations,
out DDDToolkit.Exceptions.InvariantViolationException? seamFailure)
{
foreach (var invariant in __invariants)
{
var failure = invariant.Check(this);
if (failure is not null)
{
violations ??= new System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>();
violations.Add(new DDDToolkit.Invariants.InvariantViolation(invariant.Code, failure.Message, typeof(Shop.Order), Id) { Arguments = failure.Arguments });
}
}
seamFailure = null;
try
{
CheckInvariants();
}
catch (DDDToolkit.Exceptions.InvariantViolationException failure)
{
seamFailure = failure;
violations ??= new System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>();
var reported = failure.Violations;
if (reported.Count == 0)
{
violations.Add(new DDDToolkit.Invariants.InvariantViolation(DDDToolkit.Invariants.InvariantViolation.SeamCode, failure.Message, typeof(Shop.Order), Id));
}
else
{
for (var index = 0; index < reported.Count; index++)
{
violations.Add(new DDDToolkit.Invariants.InvariantViolation(DDDToolkit.Invariants.InvariantViolation.SeamCode, reported[index], typeof(Shop.Order), Id));
}
}
}
}
private void CollectChildInvariantViolations(ref System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>? violations)
{
foreach (var child in _lines)
{
if (child is null)
{
continue;
}
var broken = child.GetInvariantViolations();
if (broken.Count == 0)
{
continue;
}
violations ??= new System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>();
for (var index = 0; index < broken.Count; index++)
{
violations.Add(broken[index]);
}
}
}
private void ThrowInvariantViolations(
System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation> violations,
DDDToolkit.Exceptions.InvariantViolationException? seamFailure)
{
throw new DDDToolkit.Exceptions.InvariantViolationException(typeof(Shop.Order), Id, violations, seamFailure);
}
public override System.Collections.Generic.IReadOnlyList<DDDToolkit.Invariants.InvariantViolation> GetOwnInvariantViolations()
{
System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>? violations = null;
CollectInvariantViolations(ref violations, out _);
if (violations is null)
{
return System.Array.Empty<DDDToolkit.Invariants.InvariantViolation>();
}
return violations;
}
public override void EnsureOwnInvariants()
{
System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>? violations = null;
CollectInvariantViolations(ref violations, out var seamFailure);
if (violations is null)
{
return;
}
ThrowInvariantViolations(violations, seamFailure);
}
public override System.Collections.Generic.IReadOnlyList<DDDToolkit.Invariants.InvariantViolation> GetInvariantViolations()
{
System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>? violations = null;
CollectInvariantViolations(ref violations, out _);
CollectChildInvariantViolations(ref violations);
if (violations is null)
{
return System.Array.Empty<DDDToolkit.Invariants.InvariantViolation>();
}
return violations;
}
public override void EnsureInvariants()
{
System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>? violations = null;
CollectInvariantViolations(ref violations, out var seamFailure);
CollectChildInvariantViolations(ref violations);
if (violations is null)
{
return;
}
ThrowInvariantViolations(violations, seamFailure);
}
private readonly System.Collections.Generic.List<Shop.OrderLine> _lines = new();
private System.Collections.Generic.IReadOnlyList<Shop.OrderLine>? __linesView;
[Microsoft.EntityFrameworkCore.BackingField(nameof(_lines))]
public partial System.Collections.Generic.IReadOnlyList<Shop.OrderLine> Lines => __linesView ??= _lines.AsReadOnly();
}
namespace Shop;
[System.Text.Json.Serialization.JsonConverter(typeof(OrderId.SystemTextJsonConverter))]
public readonly partial record struct OrderId : DDDToolkit.Abstractions.Interfaces.IEntityId<System.Guid>, System.IComparable<OrderId>, System.IParsable<OrderId>
{
public const string IdPrefix = "ORD";
public System.Guid Value { get; }
public OrderId(System.Guid value)
{
Value = value;
}
public static OrderId Empty => default;
public bool IsEmpty => System.Collections.Generic.EqualityComparer<System.Guid>.Default.Equals(Value, default);
public static OrderId CreateUnique() => new(System.Guid.NewGuid());
#if NET9_0_OR_GREATER
public static OrderId CreateSequential() => new(System.Guid.CreateVersion7());
#endif
public override string ToString()
=> IdPrefix.Length == 0
? string.Create(System.Globalization.CultureInfo.InvariantCulture, $"{Value}")
: string.Create(System.Globalization.CultureInfo.InvariantCulture, $"{IdPrefix}_{Value}");
public int CompareTo(OrderId other) => System.Collections.Generic.Comparer<System.Guid>.Default.Compare(Value, other.Value);
public static explicit operator System.Guid(OrderId id) => id.Value;
public static explicit operator OrderId(System.Guid value) => new(value);
public static OrderId Parse(string input)
{
if (TryParse(input, out var result))
{
return result;
}
throw new System.FormatException($"'{input}' is not a valid OrderId.");
}
public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, out OrderId result)
{
result = default;
if (input is null)
{
return false;
}
if (IdPrefix.Length != 0 && input.StartsWith(IdPrefix + "_", System.StringComparison.Ordinal))
{
input = input.Substring(IdPrefix.Length + 1);
}
if (!System.Guid.TryParse(input, System.Globalization.CultureInfo.InvariantCulture, out var value))
{
return false;
}
result = new(value);
return true;
}
static OrderId System.IParsable<OrderId>.Parse(string s, System.IFormatProvider? provider) => Parse(s);
static bool System.IParsable<OrderId>.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? s, System.IFormatProvider? provider, out OrderId result) => TryParse(s, out result);
public sealed class SystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter<OrderId>
{
public override OrderId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
{
var value = System.Text.Json.JsonSerializer.Deserialize<System.Guid>(ref reader, options);
return new(value);
}
public override void Write(System.Text.Json.Utf8JsonWriter writer, OrderId value, System.Text.Json.JsonSerializerOptions options)
=> System.Text.Json.JsonSerializer.Serialize(writer, value.Value, options);
public override OrderId ReadAsPropertyName(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
=> Parse(reader.GetString() ?? throw new System.Text.Json.JsonException("Cannot convert null to OrderId."));
public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, OrderId value, System.Text.Json.JsonSerializerOptions options)
=> writer.WritePropertyName(value.ToString());
}
}
namespace Shop;
partial record Address : DDDToolkit.BaseTypes.ValueObject, DDDToolkit.Validation.IValidatable<ValidAddress>
{
[System.Text.Json.Serialization.JsonInclude]
public string Street { get; protected init; } = Street;
[System.Text.Json.Serialization.JsonInclude]
public string City { get; protected init; } = City;
[DDDToolkit.Abstractions.Attributes.Internal]
protected override System.Collections.Generic.IEnumerable<object?> GetEqualityComponents()
{
yield return Street;
yield return City;
}
public virtual bool Equals(Address? other)
{
if (other is null)
{
return false;
}
if (EqualityContract != other.EqualityContract)
{
return false;
}
return System.Linq.Enumerable.SequenceEqual(GetEqualityComponents(), other.GetEqualityComponents());
}
public override int GetHashCode()
=> System.Linq.Enumerable.Aggregate(
System.Linq.Enumerable.Select(GetEqualityComponents(), static component => component?.GetHashCode() ?? 0),
static (left, right) => left ^ right);
[System.Text.Json.Serialization.JsonConstructor]
protected Address() : this(default(string)!, default(string)!)
{
}
[DDDToolkit.Abstractions.Attributes.Internal]
public ValidAddress ToValid() => new(this);
[DDDToolkit.Abstractions.Attributes.Internal]
[HotChocolate.GraphQLIgnoreAttribute]
public virtual Address With(DDDToolkit.BaseTypes.Optional<string> street = default, DDDToolkit.BaseTypes.Optional<string> city = default)
=> this with { Street = street.Or(Street), City = city.Or(City) };
}
public partial record ValidAddress : Address, DDDToolkit.Abstractions.Interfaces.IAlwaysValid
{
public ValidAddress(Address value) : base(value)
{
value.EnsureValidated();
_isValid = true;
}
[DDDToolkit.Abstractions.Attributes.Internal]
protected override System.Collections.Generic.IEnumerable<object?> GetEqualityComponents()
{
yield return Street;
yield return City;
}
public virtual bool Equals(ValidAddress? other)
{
if (other is null)
{
return false;
}
if (EqualityContract != other.EqualityContract)
{
return false;
}
return System.Linq.Enumerable.SequenceEqual(GetEqualityComponents(), other.GetEqualityComponents());
}
public override int GetHashCode() => base.GetHashCode();
[DDDToolkit.Abstractions.Attributes.Internal]
[HotChocolate.GraphQLIgnoreAttribute]
public override ValidAddress With(DDDToolkit.BaseTypes.Optional<string> street = default, DDDToolkit.BaseTypes.Optional<string> city = default)
=> new(base.With(street, city));
}
namespace Shop;
partial class OrderLine : DDDToolkit.BaseTypes.Entity<Shop.OrderLineId>
{
protected OrderLine()
{
}
partial void CheckInvariants();
private void CollectInvariantViolations(
ref System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>? violations,
out DDDToolkit.Exceptions.InvariantViolationException? seamFailure)
{
seamFailure = null;
try
{
CheckInvariants();
}
catch (DDDToolkit.Exceptions.InvariantViolationException failure)
{
seamFailure = failure;
violations ??= new System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>();
var reported = failure.Violations;
if (reported.Count == 0)
{
violations.Add(new DDDToolkit.Invariants.InvariantViolation(DDDToolkit.Invariants.InvariantViolation.SeamCode, failure.Message, typeof(Shop.OrderLine), Id));
}
else
{
for (var index = 0; index < reported.Count; index++)
{
violations.Add(new DDDToolkit.Invariants.InvariantViolation(DDDToolkit.Invariants.InvariantViolation.SeamCode, reported[index], typeof(Shop.OrderLine), Id));
}
}
}
}
public override System.Collections.Generic.IReadOnlyList<DDDToolkit.Invariants.InvariantViolation> GetOwnInvariantViolations()
{
System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>? violations = null;
CollectInvariantViolations(ref violations, out _);
if (violations is null)
{
return System.Array.Empty<DDDToolkit.Invariants.InvariantViolation>();
}
return violations;
}
public override void EnsureOwnInvariants()
{
CheckInvariants();
}
public override System.Collections.Generic.IReadOnlyList<DDDToolkit.Invariants.InvariantViolation> GetInvariantViolations() => GetOwnInvariantViolations();
public override void EnsureInvariants()
{
CheckInvariants();
}
}
namespace DDDToolkit.Website.Sample;
public static class ShopEventNames
{
public const string OrderPlaced = "shop.order-placed";
}
namespace Shop;
[System.Text.Json.Serialization.JsonConverter(typeof(OrderLineId.SystemTextJsonConverter))]
public readonly partial record struct OrderLineId : DDDToolkit.Abstractions.Interfaces.IEntityId<System.Guid>, System.IComparable<OrderLineId>, System.IParsable<OrderLineId>
{
public const string IdPrefix = "LINE";
public System.Guid Value { get; }
public OrderLineId(System.Guid value)
{
Value = value;
}
public static OrderLineId Empty => default;
public bool IsEmpty => System.Collections.Generic.EqualityComparer<System.Guid>.Default.Equals(Value, default);
public static OrderLineId CreateUnique() => new(System.Guid.NewGuid());
#if NET9_0_OR_GREATER
public static OrderLineId CreateSequential() => new(System.Guid.CreateVersion7());
#endif
public override string ToString()
=> IdPrefix.Length == 0
? string.Create(System.Globalization.CultureInfo.InvariantCulture, $"{Value}")
: string.Create(System.Globalization.CultureInfo.InvariantCulture, $"{IdPrefix}_{Value}");
public int CompareTo(OrderLineId other) => System.Collections.Generic.Comparer<System.Guid>.Default.Compare(Value, other.Value);
public static explicit operator System.Guid(OrderLineId id) => id.Value;
public static explicit operator OrderLineId(System.Guid value) => new(value);
public static OrderLineId Parse(string input)
{
if (TryParse(input, out var result))
{
return result;
}
throw new System.FormatException($"'{input}' is not a valid OrderLineId.");
}
public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, out OrderLineId result)
{
result = default;
if (input is null)
{
return false;
}
if (IdPrefix.Length != 0 && input.StartsWith(IdPrefix + "_", System.StringComparison.Ordinal))
{
input = input.Substring(IdPrefix.Length + 1);
}
if (!System.Guid.TryParse(input, System.Globalization.CultureInfo.InvariantCulture, out var value))
{
return false;
}
result = new(value);
return true;
}
static OrderLineId System.IParsable<OrderLineId>.Parse(string s, System.IFormatProvider? provider) => Parse(s);
static bool System.IParsable<OrderLineId>.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? s, System.IFormatProvider? provider, out OrderLineId result) => TryParse(s, out result);
public sealed class SystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter<OrderLineId>
{
public override OrderLineId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
{
var value = System.Text.Json.JsonSerializer.Deserialize<System.Guid>(ref reader, options);
return new(value);
}
public override void Write(System.Text.Json.Utf8JsonWriter writer, OrderLineId value, System.Text.Json.JsonSerializerOptions options)
=> System.Text.Json.JsonSerializer.Serialize(writer, value.Value, options);
public override OrderLineId ReadAsPropertyName(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
=> Parse(reader.GetString() ?? throw new System.Text.Json.JsonException("Cannot convert null to OrderLineId."));
public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, OrderLineId value, System.Text.Json.JsonSerializerOptions options)
=> writer.WritePropertyName(value.ToString());
}
}
namespace Shop;
[System.ComponentModel.DataAnnotations.Schema.ComplexType]
partial record Address
{
}
[System.ComponentModel.DataAnnotations.Schema.ComplexType]
partial record ValidAddress
{
}
namespace DDDToolkit.Website.Sample.Converters;
public static class ConverterExtensions
{
public static Microsoft.EntityFrameworkCore.ModelConfigurationBuilder AddShopConverters(this Microsoft.EntityFrameworkCore.ModelConfigurationBuilder modelConfigurationBuilder)
{
modelConfigurationBuilder.Properties<Shop.OrderId>().HaveConversion<Shop.OrderId.OrderIdConverter>();
modelConfigurationBuilder.DefaultTypeMapping<Shop.OrderId>().HasConversion<Shop.OrderId.OrderIdConverter>();
modelConfigurationBuilder.Properties<Shop.OrderLineId>().HaveConversion<Shop.OrderLineId.OrderLineIdConverter>();
modelConfigurationBuilder.DefaultTypeMapping<Shop.OrderLineId>().HasConversion<Shop.OrderLineId.OrderLineIdConverter>();
return modelConfigurationBuilder;
}
}
namespace DDDToolkit.Website.Sample.IntegrationEvents;
public static class IntegrationEventExtensions
{
public static DDDToolkit.EntityFramework.Options.OutboxOptions AddShopIntegrationEvents(this DDDToolkit.EntityFramework.Options.OutboxOptions outbox)
{
System.ArgumentNullException.ThrowIfNull(outbox);
outbox.RegisterEvent<Shop.OrderPlaced>("shop.order-placed", 1);
return outbox;
}
public static DDDToolkit.EntityFramework.Integration.IntegrationEventContractRegistry AddShopIntegrationEvents(this DDDToolkit.EntityFramework.Integration.IntegrationEventContractRegistry contracts)
{
System.ArgumentNullException.ThrowIfNull(contracts);
return contracts;
}
public static DDDToolkit.EntityFramework.Integration.ModuleIntegrationEvents<TContext> AddShopIntegrationEvents<TContext>(this DDDToolkit.EntityFramework.Integration.ModuleIntegrationEvents<TContext> module) where TContext : Microsoft.EntityFrameworkCore.DbContext
{
System.ArgumentNullException.ThrowIfNull(module);
return module;
}
}
namespace Shop;
public readonly partial record struct OrderId
{
public sealed class OrderIdConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<Shop.OrderId, System.Guid>
{
public OrderIdConverter() : base(static v => v.Value, static v => new Shop.OrderId(v))
{
}
}
}
namespace Shop;
[Microsoft.EntityFrameworkCore.Owned]
partial class OrderLine
{
}
namespace Shop;
public readonly partial record struct OrderLineId
{
public sealed class OrderLineIdConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<Shop.OrderLineId, System.Guid>
{
public OrderLineIdConverter() : base(static v => v.Value, static v => new Shop.OrderLineId(v))
{
}
}
}
using HotChocolate;
using HotChocolate.Types;
using Microsoft.Extensions.DependencyInjection;
namespace DDDToolkit.Website.Sample.GraphQl;
public static class HotChocolateExtensions
{
public static HotChocolate.Execution.Configuration.IRequestExecutorBuilder AddShopGraphQlRuntimeBindings(this HotChocolate.Execution.Configuration.IRequestExecutorBuilder builder)
{
builder.BindRuntimeType<Shop.OrderId, HotChocolate.Types.UuidType>();
builder.AddTypeConverter<Shop.OrderId.ChangeTypeProvider>();
builder.AddNodeIdValueSerializer<Shop.OrderId.NodeIdValueSerializer>();
builder.BindRuntimeType<Shop.OrderLineId, HotChocolate.Types.UuidType>();
builder.AddTypeConverter<Shop.OrderLineId.ChangeTypeProvider>();
builder.AddNodeIdValueSerializer<Shop.OrderLineId.NodeIdValueSerializer>();
return builder;
}
}
namespace Shop;
public readonly partial record struct OrderId
{
public sealed class ChangeTypeProvider : HotChocolate.Utilities.IChangeTypeProvider
{
public bool TryCreateConverter(System.Type source, System.Type target, HotChocolate.Utilities.ChangeTypeProvider root, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out HotChocolate.Utilities.ChangeType? converter)
{
if (source == typeof(Shop.OrderId) && target == typeof(System.Guid))
{
converter = value => ((Shop.OrderId)value!).Value;
return true;
}
if (source == typeof(System.Guid) && target == typeof(Shop.OrderId))
{
converter = value => new Shop.OrderId((System.Guid)value!);
return true;
}
converter = null;
return false;
}
}
public sealed class NodeIdValueSerializer : HotChocolate.Types.Relay.CompositeNodeIdValueSerializer<Shop.OrderId>
{
protected override HotChocolate.Types.Relay.NodeIdFormatterResult Format(System.Span<byte> buffer, Shop.OrderId value, out int written)
{
return TryFormatIdPart(buffer, value.Value, out written)
? HotChocolate.Types.Relay.NodeIdFormatterResult.Success
: HotChocolate.Types.Relay.NodeIdFormatterResult.BufferTooSmall;
}
protected override bool TryParse(System.ReadOnlySpan<byte> buffer, out Shop.OrderId value)
{
if (TryParseIdPart(buffer, out System.Guid raw, out _))
{
value = new Shop.OrderId(raw);
return true;
}
value = default;
return false;
}
}
}
namespace Shop;
public readonly partial record struct OrderLineId
{
public sealed class ChangeTypeProvider : HotChocolate.Utilities.IChangeTypeProvider
{
public bool TryCreateConverter(System.Type source, System.Type target, HotChocolate.Utilities.ChangeTypeProvider root, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out HotChocolate.Utilities.ChangeType? converter)
{
if (source == typeof(Shop.OrderLineId) && target == typeof(System.Guid))
{
converter = value => ((Shop.OrderLineId)value!).Value;
return true;
}
if (source == typeof(System.Guid) && target == typeof(Shop.OrderLineId))
{
converter = value => new Shop.OrderLineId((System.Guid)value!);
return true;
}
converter = null;
return false;
}
}
public sealed class NodeIdValueSerializer : HotChocolate.Types.Relay.CompositeNodeIdValueSerializer<Shop.OrderLineId>
{
protected override HotChocolate.Types.Relay.NodeIdFormatterResult Format(System.Span<byte> buffer, Shop.OrderLineId value, out int written)
{
return TryFormatIdPart(buffer, value.Value, out written)
? HotChocolate.Types.Relay.NodeIdFormatterResult.Success
: HotChocolate.Types.Relay.NodeIdFormatterResult.BufferTooSmall;
}
protected override bool TryParse(System.ReadOnlySpan<byte> buffer, out Shop.OrderLineId value)
{
if (TryParseIdPart(buffer, out System.Guid raw, out _))
{
value = new Shop.OrderLineId(raw);
return true;
}
value = default;
return false;
}
}
}
namespace Shop;
partial class Order : DDDToolkit.BaseTypes.AggregateRoot<Shop.OrderId>
{
protected Order()
{
}
partial void CheckInvariants();
private static readonly DDDToolkit.Invariants.IInvariant<Shop.Order>[] __invariants =
[
new Shop.Order.MustHaveLines(),
];
private void CollectInvariantViolations(
ref System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>? violations,
out DDDToolkit.Exceptions.InvariantViolationException? seamFailure)
{
foreach (var invariant in __invariants)
{
var failure = invariant.Check(this);
if (failure is not null)
{
violations ??= new System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>();
violations.Add(new DDDToolkit.Invariants.InvariantViolation(invariant.Code, failure.Message, typeof(Shop.Order), Id) { Arguments = failure.Arguments });
}
}
seamFailure = null;
try
{
CheckInvariants();
}
catch (DDDToolkit.Exceptions.InvariantViolationException failure)
{
seamFailure = failure;
violations ??= new System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>();
var reported = failure.Violations;
if (reported.Count == 0)
{
violations.Add(new DDDToolkit.Invariants.InvariantViolation(DDDToolkit.Invariants.InvariantViolation.SeamCode, failure.Message, typeof(Shop.Order), Id));
}
else
{
for (var index = 0; index < reported.Count; index++)
{
violations.Add(new DDDToolkit.Invariants.InvariantViolation(DDDToolkit.Invariants.InvariantViolation.SeamCode, reported[index], typeof(Shop.Order), Id));
}
}
}
}
private void CollectChildInvariantViolations(ref System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>? violations)
{
foreach (var child in _lines)
{
if (child is null)
{
continue;
}
var broken = child.GetInvariantViolations();
if (broken.Count == 0)
{
continue;
}
violations ??= new System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>();
for (var index = 0; index < broken.Count; index++)
{
violations.Add(broken[index]);
}
}
}
private void ThrowInvariantViolations(
System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation> violations,
DDDToolkit.Exceptions.InvariantViolationException? seamFailure)
{
throw new DDDToolkit.Exceptions.InvariantViolationException(typeof(Shop.Order), Id, violations, seamFailure);
}
public override System.Collections.Generic.IReadOnlyList<DDDToolkit.Invariants.InvariantViolation> GetOwnInvariantViolations()
{
System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>? violations = null;
CollectInvariantViolations(ref violations, out _);
if (violations is null)
{
return System.Array.Empty<DDDToolkit.Invariants.InvariantViolation>();
}
return violations;
}
public override void EnsureOwnInvariants()
{
System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>? violations = null;
CollectInvariantViolations(ref violations, out var seamFailure);
if (violations is null)
{
return;
}
ThrowInvariantViolations(violations, seamFailure);
}
public override System.Collections.Generic.IReadOnlyList<DDDToolkit.Invariants.InvariantViolation> GetInvariantViolations()
{
System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>? violations = null;
CollectInvariantViolations(ref violations, out _);
CollectChildInvariantViolations(ref violations);
if (violations is null)
{
return System.Array.Empty<DDDToolkit.Invariants.InvariantViolation>();
}
return violations;
}
public override void EnsureInvariants()
{
System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>? violations = null;
CollectInvariantViolations(ref violations, out var seamFailure);
CollectChildInvariantViolations(ref violations);
if (violations is null)
{
return;
}
ThrowInvariantViolations(violations, seamFailure);
}
private readonly System.Collections.Generic.List<Shop.OrderLine> _lines = new();
private System.Collections.Generic.IReadOnlyList<Shop.OrderLine>? __linesView;
[Microsoft.EntityFrameworkCore.BackingField(nameof(_lines))]
public partial System.Collections.Generic.IReadOnlyList<Shop.OrderLine> Lines => __linesView ??= _lines.AsReadOnly();
}
namespace Shop;
[System.Text.Json.Serialization.JsonConverter(typeof(OrderId.SystemTextJsonConverter))]
public readonly partial record struct OrderId : DDDToolkit.Abstractions.Interfaces.IEntityId<System.Guid>, System.IComparable<OrderId>, System.IParsable<OrderId>
{
public const string IdPrefix = "ORD";
public System.Guid Value { get; }
public OrderId(System.Guid value)
{
Value = value;
}
public static OrderId Empty => default;
public bool IsEmpty => System.Collections.Generic.EqualityComparer<System.Guid>.Default.Equals(Value, default);
public static OrderId CreateUnique() => new(System.Guid.NewGuid());
#if NET9_0_OR_GREATER
public static OrderId CreateSequential() => new(System.Guid.CreateVersion7());
#endif
public override string ToString()
=> IdPrefix.Length == 0
? string.Create(System.Globalization.CultureInfo.InvariantCulture, $"{Value}")
: string.Create(System.Globalization.CultureInfo.InvariantCulture, $"{IdPrefix}_{Value}");
public int CompareTo(OrderId other) => System.Collections.Generic.Comparer<System.Guid>.Default.Compare(Value, other.Value);
public static explicit operator System.Guid(OrderId id) => id.Value;
public static explicit operator OrderId(System.Guid value) => new(value);
public static OrderId Parse(string input)
{
if (TryParse(input, out var result))
{
return result;
}
throw new System.FormatException($"'{input}' is not a valid OrderId.");
}
public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, out OrderId result)
{
result = default;
if (input is null)
{
return false;
}
if (IdPrefix.Length != 0 && input.StartsWith(IdPrefix + "_", System.StringComparison.Ordinal))
{
input = input.Substring(IdPrefix.Length + 1);
}
if (!System.Guid.TryParse(input, System.Globalization.CultureInfo.InvariantCulture, out var value))
{
return false;
}
result = new(value);
return true;
}
static OrderId System.IParsable<OrderId>.Parse(string s, System.IFormatProvider? provider) => Parse(s);
static bool System.IParsable<OrderId>.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? s, System.IFormatProvider? provider, out OrderId result) => TryParse(s, out result);
public sealed class SystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter<OrderId>
{
public override OrderId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
{
var value = System.Text.Json.JsonSerializer.Deserialize<System.Guid>(ref reader, options);
return new(value);
}
public override void Write(System.Text.Json.Utf8JsonWriter writer, OrderId value, System.Text.Json.JsonSerializerOptions options)
=> System.Text.Json.JsonSerializer.Serialize(writer, value.Value, options);
public override OrderId ReadAsPropertyName(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
=> Parse(reader.GetString() ?? throw new System.Text.Json.JsonException("Cannot convert null to OrderId."));
public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, OrderId value, System.Text.Json.JsonSerializerOptions options)
=> writer.WritePropertyName(value.ToString());
}
}
namespace Shop;
partial record Address : DDDToolkit.BaseTypes.ValueObject, DDDToolkit.Validation.IValidatable<ValidAddress>
{
[System.Text.Json.Serialization.JsonInclude]
public string Street { get; protected init; } = Street;
[System.Text.Json.Serialization.JsonInclude]
public string City { get; protected init; } = City;
[DDDToolkit.Abstractions.Attributes.Internal]
protected override System.Collections.Generic.IEnumerable<object?> GetEqualityComponents()
{
yield return Street;
yield return City;
}
public virtual bool Equals(Address? other)
{
if (other is null)
{
return false;
}
if (EqualityContract != other.EqualityContract)
{
return false;
}
return System.Linq.Enumerable.SequenceEqual(GetEqualityComponents(), other.GetEqualityComponents());
}
public override int GetHashCode()
=> System.Linq.Enumerable.Aggregate(
System.Linq.Enumerable.Select(GetEqualityComponents(), static component => component?.GetHashCode() ?? 0),
static (left, right) => left ^ right);
[System.Text.Json.Serialization.JsonConstructor]
protected Address() : this(default(string)!, default(string)!)
{
}
[DDDToolkit.Abstractions.Attributes.Internal]
public ValidAddress ToValid() => new(this);
[DDDToolkit.Abstractions.Attributes.Internal]
[HotChocolate.GraphQLIgnoreAttribute]
public virtual Address With(DDDToolkit.BaseTypes.Optional<string> street = default, DDDToolkit.BaseTypes.Optional<string> city = default)
=> this with { Street = street.Or(Street), City = city.Or(City) };
}
public partial record ValidAddress : Address, DDDToolkit.Abstractions.Interfaces.IAlwaysValid
{
public ValidAddress(Address value) : base(value)
{
value.EnsureValidated();
_isValid = true;
}
[DDDToolkit.Abstractions.Attributes.Internal]
protected override System.Collections.Generic.IEnumerable<object?> GetEqualityComponents()
{
yield return Street;
yield return City;
}
public virtual bool Equals(ValidAddress? other)
{
if (other is null)
{
return false;
}
if (EqualityContract != other.EqualityContract)
{
return false;
}
return System.Linq.Enumerable.SequenceEqual(GetEqualityComponents(), other.GetEqualityComponents());
}
public override int GetHashCode() => base.GetHashCode();
[DDDToolkit.Abstractions.Attributes.Internal]
[HotChocolate.GraphQLIgnoreAttribute]
public override ValidAddress With(DDDToolkit.BaseTypes.Optional<string> street = default, DDDToolkit.BaseTypes.Optional<string> city = default)
=> new(base.With(street, city));
}
namespace Shop;
partial class OrderLine : DDDToolkit.BaseTypes.Entity<Shop.OrderLineId>
{
protected OrderLine()
{
}
partial void CheckInvariants();
private void CollectInvariantViolations(
ref System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>? violations,
out DDDToolkit.Exceptions.InvariantViolationException? seamFailure)
{
seamFailure = null;
try
{
CheckInvariants();
}
catch (DDDToolkit.Exceptions.InvariantViolationException failure)
{
seamFailure = failure;
violations ??= new System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>();
var reported = failure.Violations;
if (reported.Count == 0)
{
violations.Add(new DDDToolkit.Invariants.InvariantViolation(DDDToolkit.Invariants.InvariantViolation.SeamCode, failure.Message, typeof(Shop.OrderLine), Id));
}
else
{
for (var index = 0; index < reported.Count; index++)
{
violations.Add(new DDDToolkit.Invariants.InvariantViolation(DDDToolkit.Invariants.InvariantViolation.SeamCode, reported[index], typeof(Shop.OrderLine), Id));
}
}
}
}
public override System.Collections.Generic.IReadOnlyList<DDDToolkit.Invariants.InvariantViolation> GetOwnInvariantViolations()
{
System.Collections.Generic.List<DDDToolkit.Invariants.InvariantViolation>? violations = null;
CollectInvariantViolations(ref violations, out _);
if (violations is null)
{
return System.Array.Empty<DDDToolkit.Invariants.InvariantViolation>();
}
return violations;
}
public override void EnsureOwnInvariants()
{
CheckInvariants();
}
public override System.Collections.Generic.IReadOnlyList<DDDToolkit.Invariants.InvariantViolation> GetInvariantViolations() => GetOwnInvariantViolations();
public override void EnsureInvariants()
{
CheckInvariants();
}
}
namespace DDDToolkit.Website.Sample;
public static class ShopEventNames
{
public const string OrderPlaced = "shop.order-placed";
}
namespace Shop;
[System.Text.Json.Serialization.JsonConverter(typeof(OrderLineId.SystemTextJsonConverter))]
public readonly partial record struct OrderLineId : DDDToolkit.Abstractions.Interfaces.IEntityId<System.Guid>, System.IComparable<OrderLineId>, System.IParsable<OrderLineId>
{
public const string IdPrefix = "LINE";
public System.Guid Value { get; }
public OrderLineId(System.Guid value)
{
Value = value;
}
public static OrderLineId Empty => default;
public bool IsEmpty => System.Collections.Generic.EqualityComparer<System.Guid>.Default.Equals(Value, default);
public static OrderLineId CreateUnique() => new(System.Guid.NewGuid());
#if NET9_0_OR_GREATER
public static OrderLineId CreateSequential() => new(System.Guid.CreateVersion7());
#endif
public override string ToString()
=> IdPrefix.Length == 0
? string.Create(System.Globalization.CultureInfo.InvariantCulture, $"{Value}")
: string.Create(System.Globalization.CultureInfo.InvariantCulture, $"{IdPrefix}_{Value}");
public int CompareTo(OrderLineId other) => System.Collections.Generic.Comparer<System.Guid>.Default.Compare(Value, other.Value);
public static explicit operator System.Guid(OrderLineId id) => id.Value;
public static explicit operator OrderLineId(System.Guid value) => new(value);
public static OrderLineId Parse(string input)
{
if (TryParse(input, out var result))
{
return result;
}
throw new System.FormatException($"'{input}' is not a valid OrderLineId.");
}
public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? input, out OrderLineId result)
{
result = default;
if (input is null)
{
return false;
}
if (IdPrefix.Length != 0 && input.StartsWith(IdPrefix + "_", System.StringComparison.Ordinal))
{
input = input.Substring(IdPrefix.Length + 1);
}
if (!System.Guid.TryParse(input, System.Globalization.CultureInfo.InvariantCulture, out var value))
{
return false;
}
result = new(value);
return true;
}
static OrderLineId System.IParsable<OrderLineId>.Parse(string s, System.IFormatProvider? provider) => Parse(s);
static bool System.IParsable<OrderLineId>.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? s, System.IFormatProvider? provider, out OrderLineId result) => TryParse(s, out result);
public sealed class SystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter<OrderLineId>
{
public override OrderLineId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
{
var value = System.Text.Json.JsonSerializer.Deserialize<System.Guid>(ref reader, options);
return new(value);
}
public override void Write(System.Text.Json.Utf8JsonWriter writer, OrderLineId value, System.Text.Json.JsonSerializerOptions options)
=> System.Text.Json.JsonSerializer.Serialize(writer, value.Value, options);
public override OrderLineId ReadAsPropertyName(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
=> Parse(reader.GetString() ?? throw new System.Text.Json.JsonException("Cannot convert null to OrderLineId."));
public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, OrderLineId value, System.Text.Json.JsonSerializerOptions options)
=> writer.WritePropertyName(value.ToString());
}
}
namespace Shop;
[System.ComponentModel.DataAnnotations.Schema.ComplexType]
partial record Address
{
}
[System.ComponentModel.DataAnnotations.Schema.ComplexType]
partial record ValidAddress
{
}
namespace DDDToolkit.Website.Sample.Converters;
public static class ConverterExtensions
{
public static Microsoft.EntityFrameworkCore.ModelConfigurationBuilder AddShopConverters(this Microsoft.EntityFrameworkCore.ModelConfigurationBuilder modelConfigurationBuilder)
{
modelConfigurationBuilder.Properties<Shop.OrderId>().HaveConversion<Shop.OrderId.OrderIdConverter>();
modelConfigurationBuilder.DefaultTypeMapping<Shop.OrderId>().HasConversion<Shop.OrderId.OrderIdConverter>();
modelConfigurationBuilder.Properties<Shop.OrderLineId>().HaveConversion<Shop.OrderLineId.OrderLineIdConverter>();
modelConfigurationBuilder.DefaultTypeMapping<Shop.OrderLineId>().HasConversion<Shop.OrderLineId.OrderLineIdConverter>();
return modelConfigurationBuilder;
}
}
namespace DDDToolkit.Website.Sample.IntegrationEvents;
public static class IntegrationEventExtensions
{
public static DDDToolkit.EntityFramework.Options.OutboxOptions AddShopIntegrationEvents(this DDDToolkit.EntityFramework.Options.OutboxOptions outbox)
{
System.ArgumentNullException.ThrowIfNull(outbox);
outbox.RegisterEvent<Shop.OrderPlaced>("shop.order-placed", 1);
return outbox;
}
public static DDDToolkit.EntityFramework.Integration.IntegrationEventContractRegistry AddShopIntegrationEvents(this DDDToolkit.EntityFramework.Integration.IntegrationEventContractRegistry contracts)
{
System.ArgumentNullException.ThrowIfNull(contracts);
return contracts;
}
public static DDDToolkit.EntityFramework.Integration.ModuleIntegrationEvents<TContext> AddShopIntegrationEvents<TContext>(this DDDToolkit.EntityFramework.Integration.ModuleIntegrationEvents<TContext> module) where TContext : Microsoft.EntityFrameworkCore.DbContext
{
System.ArgumentNullException.ThrowIfNull(module);
return module;
}
}
namespace Shop;
public readonly partial record struct OrderId
{
public sealed class OrderIdConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<Shop.OrderId, System.Guid>
{
public OrderIdConverter() : base(static v => v.Value, static v => new Shop.OrderId(v))
{
}
}
}
namespace Shop;
[Microsoft.EntityFrameworkCore.Owned]
partial class OrderLine
{
}
namespace Shop;
public readonly partial record struct OrderLineId
{
public sealed class OrderLineIdConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<Shop.OrderLineId, System.Guid>
{
public OrderLineIdConverter() : base(static v => v.Value, static v => new Shop.OrderLineId(v))
{
}
}
}
using HotChocolate;
using HotChocolate.Types;
using Microsoft.Extensions.DependencyInjection;
namespace DDDToolkit.Website.Sample.GraphQl;
public static class HotChocolateExtensions
{
public static HotChocolate.Execution.Configuration.IRequestExecutorBuilder AddShopGraphQlRuntimeBindings(this HotChocolate.Execution.Configuration.IRequestExecutorBuilder builder)
{
builder.BindRuntimeType<Shop.OrderId, HotChocolate.Types.UuidType>();
builder.AddTypeConverter<Shop.OrderId.ChangeTypeProvider>();
builder.AddNodeIdValueSerializer<Shop.OrderId.NodeIdValueSerializer>();
builder.BindRuntimeType<Shop.OrderLineId, HotChocolate.Types.UuidType>();
builder.AddTypeConverter<Shop.OrderLineId.ChangeTypeProvider>();
builder.AddNodeIdValueSerializer<Shop.OrderLineId.NodeIdValueSerializer>();
return builder;
}
}
namespace Shop;
public readonly partial record struct OrderId
{
public sealed class ChangeTypeProvider : HotChocolate.Utilities.IChangeTypeProvider
{
public bool TryCreateConverter(System.Type source, System.Type target, HotChocolate.Utilities.ChangeTypeProvider root, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out HotChocolate.Utilities.ChangeType? converter)
{
if (source == typeof(Shop.OrderId) && target == typeof(System.Guid))
{
converter = value => ((Shop.OrderId)value!).Value;
return true;
}
if (source == typeof(System.Guid) && target == typeof(Shop.OrderId))
{
converter = value => new Shop.OrderId((System.Guid)value!);
return true;
}
converter = null;
return false;
}
}
public sealed class NodeIdValueSerializer : HotChocolate.Types.Relay.CompositeNodeIdValueSerializer<Shop.OrderId>
{
protected override HotChocolate.Types.Relay.NodeIdFormatterResult Format(System.Span<byte> buffer, Shop.OrderId value, out int written)
{
return TryFormatIdPart(buffer, value.Value, out written)
? HotChocolate.Types.Relay.NodeIdFormatterResult.Success
: HotChocolate.Types.Relay.NodeIdFormatterResult.BufferTooSmall;
}
protected override bool TryParse(System.ReadOnlySpan<byte> buffer, out Shop.OrderId value)
{
if (TryParseIdPart(buffer, out System.Guid raw, out _))
{
value = new Shop.OrderId(raw);
return true;
}
value = default;
return false;
}
}
}
namespace Shop;
public readonly partial record struct OrderLineId
{
public sealed class ChangeTypeProvider : HotChocolate.Utilities.IChangeTypeProvider
{
public bool TryCreateConverter(System.Type source, System.Type target, HotChocolate.Utilities.ChangeTypeProvider root, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out HotChocolate.Utilities.ChangeType? converter)
{
if (source == typeof(Shop.OrderLineId) && target == typeof(System.Guid))
{
converter = value => ((Shop.OrderLineId)value!).Value;
return true;
}
if (source == typeof(System.Guid) && target == typeof(Shop.OrderLineId))
{
converter = value => new Shop.OrderLineId((System.Guid)value!);
return true;
}
converter = null;
return false;
}
}
public sealed class NodeIdValueSerializer : HotChocolate.Types.Relay.CompositeNodeIdValueSerializer<Shop.OrderLineId>
{
protected override HotChocolate.Types.Relay.NodeIdFormatterResult Format(System.Span<byte> buffer, Shop.OrderLineId value, out int written)
{
return TryFormatIdPart(buffer, value.Value, out written)
? HotChocolate.Types.Relay.NodeIdFormatterResult.Success
: HotChocolate.Types.Relay.NodeIdFormatterResult.BufferTooSmall;
}
protected override bool TryParse(System.ReadOnlySpan<byte> buffer, out Shop.OrderLineId value)
{
if (TryParseIdPart(buffer, out System.Guid raw, out _))
{
value = new Shop.OrderLineId(raw);
return true;
}
value = default;
return false;
}
}
}