TransparentValueObjects 1.0.1
dotnet add package TransparentValueObjects --version 1.0.1
NuGet\Install-Package TransparentValueObjects -Version 1.0.1
<PackageReference Include="TransparentValueObjects" Version="1.0.1" />
paket add TransparentValueObjects --version 1.0.1
#r "nuget: TransparentValueObjects, 1.0.1"
// Install TransparentValueObjects as a Cake Addin #addin nuget:?package=TransparentValueObjects&version=1.0.1 // Install TransparentValueObjects as a Cake Tool #tool nuget:?package=TransparentValueObjects&version=1.0.1
TransparentValueObjects
Source generator and analyzer to create Value Objects.
Example
using System;
using TransparentValueObjects;
[ValueObject<Guid>]
public readonly partial struct MyId { }
The attribute ValueObject<TInnerValue>
will generate a partial implementation of this readonly struct with the following defaults:
- A
public readonly TInnerValue Value
field. - A
public static T From(TInnerValue innerValue)
method that uses the private constructor. - A private constructor used by the
From
method. - A public constructor marked as
Obsolete
witherror: true
that will throw an exception if called (this behavior can be overwritten using Augments). GetHashCode
andToString
implementations that call the same methods on the inner value.- Equality methods:
object.Equals
,IEquatable<T>
andIEquatable<TInnerValue>
.==
and!=
operators.- Additional
Equals
method withIEqualityComparer<TInnerValue>
parameter.
- Explicit cast operators.
IComparable<T>
andIComparable<TInnerValue>
ifTInnerValue
implementsIComparable<TInnerValue>
.<
,<=
,>
and>=
operators.
- For
Guid
only:NewId
method that callsFrom(Guid.NewGuid())
.
You can check the test files to view the generated output.
Augments
The biggest selling point of this project is the augment feature. You can use the IAugmentWith
interface to "augment" your Value Object with additional functionality:
using System;
using TransparentValueObjects;
[ValueObject<Guid>]
public readonly partial struct SampleGuidValueObject : IAugmentWith<
DefaultValueAugment,
JsonAugment,
EfCoreAugment>
{
/// <inheritdoc/>
public static SampleGuidValueObject DefaultValue => From(Guid.Empty);
}
The following augments are currently available:
Default Value
Augments the Value Object with the IDefaultValue
interface that has a static member DefaultValue
:
public static abstract TValueObject DefaultValue { get; }
using System;
using TransparentValueObjects;
[ValueObject<Guid>]
public readonly partial struct SampleGuidValueObject : IAugmentWith<DefaultValueAugment>
{
/// <inheritdoc/>
public static SampleGuidValueObject DefaultValue => From(Guid.Empty);
}
You have to implement the DefaultValue
member when using this augment. The public constructor will now also be available:
public SampleGuidValueObject()
{
Value = DefaultValue.Value;
}
Default Equality Comparer
Augments the Value Object with the IDefaultEqualityComparer
interface that has a static member InnerValueDefaultEqualityComparer
:
public static abstract IEqualityComparer<TInnerValue> InnerValueDefaultEqualityComparer { get; }
[ValueObject<string>]
public readonly partial struct SampleStringValueObject : IAugmentWith<DefaultEqualityComparerAugment>
{
/// <inheritdoc/>
public static IEqualityComparer<string> InnerValueDefaultEqualityComparer => StringComparer.OrdinalIgnoreCase;
}
This default equality comparer will be used by the following methods:
public bool Equals(SampleStringValueObject other) => Equals(other.Value);
public bool Equals(string? other) => InnerValueDefaultEqualityComparer.Equals(Value, other);
public override int GetHashCode() => InnerValueDefaultEqualityComparer.GetHashCode(Value);
This augment is especially great for strings if you want to always use the case-insensitive equality comparer.
Json Augment
Augments the Value Object with a JSON converter:
[ValueObject<string>]
public readonly partial struct SampleStringValueObject : IAugmentWith<JsonAugment> { }
Only System.Text.Json
is currently supported! See https://github.com/erri120/TransparentValueObjects/issues/11 for Newtonsoft.Json
support.
[JsonConverter(typeof(JsonConverter))]
readonly partial struct SampleStringValueObject
{
public class JsonConverter : JsonConverter<SampleStringValueObject> { /* omitted */ }
}
The JsonConverterAttribute
will be added to the Value Object, meaning that you can use the added converter without needing to manually add it to the JSON options.
The source generator will create a custom converter for the following types:
string
Guid
Int16
Int32
Int64
UInt16
UInt32
UInt64
All other types will use a fallback converter that fetches an existing converter for TInnerValue
.
Note: If the inner value type is a reference type, like string
, then you will need to also augment the Value Object with the DefaultValueAugment
.
EF Core Augment
Augments the Value Object with a ValueConverter<T, TInnerValue>
and ValueComparer<T>
:
[ValueObject<string>]
public readonly partial struct SampleStringValueObject : IAugmentWith<EfCoreAugment> { }
public class EfCoreValueConverter : ValueConverter<SampleStringValueObject, string>
{
public EfCoreValueConverter() : this(mappingHints: null) { }
public EfCoreValueConverter(ConverterMappingHints? mappingHints = null) : base(
static value => value.Value,
static innerValue => From(innerValue),
mappingHints
) { }
}
public class EfCoreValueComparer : ValueComparer<SampleStringValueObject>
{
public EfCoreValueComparer() : base(
static (left, right) => left.Equals(right),
static value => value.GetHashCode(),
static value => From(value.Value)
) { }
/// <inheritdoc/>
public override bool Equals(SampleStringValueObject left, SampleStringValueObject right) => left.Equals(right);
/// <inheritdoc/>
public override SampleStringValueObject Snapshot(SampleStringValueObject instance) => From(instance.Value);
/// <inheritdoc/>
public override int GetHashCode(SampleStringValueObject instance) => instance.GetHashCode();
}
License
See LICENSE for details.
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- No dependencies.
NuGet packages (3)
Showing the top 3 NuGet packages that depend on TransparentValueObjects:
Package | Downloads |
---|---|
NexusMods.Hashing.xxHash64
Nexus Mods' Implementation of the xxHash64 algorithm. |
|
NexusMods.Hashing.xxHash3
Nexus Mods' Implementation of the xxHash3 algorithm. |
|
NexusMods.Hashing.xxHash3.Paths
Extension methods that combine NexusMods.Paths and NexusMods.Hashing.xxHash3. |
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on TransparentValueObjects:
Repository | Stars |
---|---|
Nexus-Mods/NexusMods.App
Home of the development of the Nexus Mods App
|