{"id":13629277,"url":"https://github.com/Cysharp/UnitGenerator","last_synced_at":"2025-04-17T08:34:36.103Z","repository":{"id":40306746,"uuid":"320112116","full_name":"Cysharp/UnitGenerator","owner":"Cysharp","description":"C# Source Generator to create value-object, inspired by units of measure.","archived":false,"fork":false,"pushed_at":"2025-03-19T06:46:10.000Z","size":188,"stargazers_count":363,"open_issues_count":2,"forks_count":20,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-04-14T23:17:02.947Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Cysharp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-12-10T00:10:19.000Z","updated_at":"2025-04-12T04:15:52.000Z","dependencies_parsed_at":"2024-03-28T10:52:45.344Z","dependency_job_id":"80ccfbc9-2d87-4677-8f4c-ced82af27dfe","html_url":"https://github.com/Cysharp/UnitGenerator","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cysharp%2FUnitGenerator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cysharp%2FUnitGenerator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cysharp%2FUnitGenerator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cysharp%2FUnitGenerator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Cysharp","download_url":"https://codeload.github.com/Cysharp/UnitGenerator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248975329,"owners_count":21192210,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T22:01:06.290Z","updated_at":"2025-04-17T08:34:36.096Z","avatar_url":"https://github.com/Cysharp.png","language":"C#","readme":"UnitGenerator\n===\n[![GitHub Actions](https://github.com/Cysharp/UnitGenerator/workflows/Build-Debug/badge.svg)](https://github.com/Cysharp/UnitGenerator/actions) [![Releases](https://img.shields.io/github/release/Cysharp/UnitGenerator.svg)](https://github.com/Cysharp/UnitGenerator/releases)\n\nC# Source Generator to create [Value object](https://en.wikipedia.org/wiki/Value_object) pattern, also inspired by [units of measure](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/units-of-measure) to support all arithmetic operators and serialization.\n\nNuGet: [UnitGenerator](https://www.nuget.org/packages/UnitGenerator)\n\n```\nInstall-Package UnitGenerator\n```\n\nExecute in Unity Game Engine is also supported, please see the [Unity](#use-for-unity) section for details.\n\n## Introduction\n\nFor example, Identifier, UserId is comparable only to UserId, and cannot be assigned to any other type. Also, arithmetic operations are not allowed.\n\n```csharp\nusing UnitGenerator;\n\n[UnitOf(typeof(int))]\npublic readonly partial struct UserId; { }\n```\n\nor when using C#11 and NET7 you can use\n\n```csharp\nusing UnitGenerator;\n\n[UnitOf\u003cint\u003e] public readonly partial struct UserId;\n```\n\nwill generates\n\n```csharp\n[System.ComponentModel.TypeConverter(typeof(UserIdTypeConverter))]\npublic readonly partial struct UserId : IEquatable\u003cUserId\u003e \n{\n    readonly int value;\n    \n    public UserId(int value)\n    {\n        this.value = value;\n    }\n\n    public readonly int AsPrimitive() =\u003e value;\n    public static explicit operator int(UserId value) =\u003e value.value;\n    public static explicit operator UserId(int value) =\u003e new UserId(value);\n    public bool Equals(UserId other) =\u003e value.Equals(other.value);\n    public override bool Equals(object? obj) =\u003e // snip...\n    public override int GetHashCode() =\u003e value.GetHashCode();\n    public override string ToString() =\u003e value.ToString();\n    public static bool operator ==(in UserId x, in UserId y) =\u003e x.value.Equals(y.value);\n    public static bool operator !=(in UserId x, in UserId y) =\u003e !x.value.Equals(y.value);\n\n    private class UserIdTypeConverter : System.ComponentModel.TypeConverter\n    {\n        // snip...\n    }\n}\n```\n\nHowever, Hp in games, should not be allowed to be assigned to other types, but should support arithmetic operations with int. For example double heal = `target.Hp = Hp.Min(target.Hp * 2, target.MaxHp)`.\n\n```csharp\n[UnitOf\u003cint\u003e(UnitGenerateOptions.ArithmeticOperator | UnitGenerateOptions.ValueArithmeticOperator | UnitGenerateOptions.Comparable | UnitGenerateOptions.MinMaxMethod)]\npublic readonly partial struct Hp;\n\n// -- generates\n\n[System.ComponentModel.TypeConverter(typeof(HpTypeConverter))]\npublic readonly partial struct Hp\n    : IEquatable\u003cHp\u003e\n#if NET7_0_OR_GREATER\n    , IEqualityOperators\u003cHp, Hp, bool\u003e\n#endif    \n    , IComparable\u003cHp\u003e\n#if NET7_0_OR_GREATER\n    , IComparisonOperators\u003cHp, Hp, bool\u003e\n#endif\n#if NET7_0_OR_GREATER\n    , IAdditionOperators\u003cHp, Hp, Hp\u003e\n    , ISubtractionOperators\u003cHp, Hp, Hp\u003e\n    , IMultiplyOperators\u003cHp, Hp, Hp\u003e\n    , IDivisionOperators\u003cHp, Hp, Hp\u003e\n    , IUnaryPlusOperators\u003cHp, Hp\u003e\n    , IUnaryNegationOperators\u003cHp, Hp\u003e\n    , IIncrementOperators\u003cHp\u003e\n    , IDecrementOperators\u003cHp\u003e\n#endif    \n{\n    readonly int value;\n\n    public Hp(int value)\n    {\n        this.value = value;\n    }\n\n    public int AsPrimitive() =\u003e value;\n    public static explicit operator int(Hp value) =\u003e value.value;\n    public static explicit operator Hp(int value) =\u003e new Hp(value);\n    public bool Equals(Hp other) =\u003e value.Equals(other.value);\n    public override bool Equals(object? obj) =\u003e // snip...\n    public override int GetHashCode() =\u003e value.GetHashCode();\n    public override string ToString() =\u003e value.ToString();\n    public static bool operator ==(in Hp x, in Hp y) =\u003e x.value.Equals(y.value);\n    public static bool operator !=(in Hp x, in Hp y) =\u003e !x.value.Equals(y.value);\n    private class HpTypeConverter : System.ComponentModel.TypeConverter { /* snip... */ }\n\n    // UnitGenerateOptions.ArithmeticOperator\n    public static Hp operator +(Hp x, Hp y) =\u003e new Hp(checked((int)(x.value + y.value)));\n    public static Hp operator -(Hp x, Hp y) =\u003e new Hp(checked((int)(x.value - y.value)));\n    public static Hp operator *(Hp x, Hp y) =\u003e new Hp(checked((int)(x.value * y.value)));\n    public static Hp operator /(Hp x, Hp y) =\u003e new Hp(checked((int)(x.value / y.value)));\n    public static Hp operator ++(Hp x) =\u003e new Hp(checked((int)(x.value + 1)));\n    public static Hp operator --(Hp x) =\u003e new Hp(checked((int)(x.value - 1)));\n    public static Hp operator +(A value) =\u003e new((int)(+value.value));\n    public static Hp operator -(A value) =\u003e new((int)(-value.value));\n\n    // UnitGenerateOptions.ValueArithmeticOperator\n    public static Hp operator +(Hp x, in int y) =\u003e new Hp(checked((int)(x.value + y)));\n    public static Hp operator -(Hp x, in int y) =\u003e new Hp(checked((int)(x.value - y)));\n    public static Hp operator *(Hp x, in int y) =\u003e new Hp(checked((int)(x.value * y)));\n    public static Hp operator /(Hp x, in int y) =\u003e new Hp(checked((int)(x.value / y)));\n\n    // UnitGenerateOptions.Comparable\n    public int CompareTo(Hp other) =\u003e value.CompareTo(other.value);\n    public static bool operator \u003e(Hp x, Hp y) =\u003e x.value \u003e y.value;\n    public static bool operator \u003c(Hp x, Hp y) =\u003e x.value \u003c y.value;\n    public static bool operator \u003e=(Hp x, Hp y) =\u003e x.value \u003e= y.value;\n    public static bool operator \u003c=(Hp x, Hp y) =\u003e x.value \u003c= y.value;\n\n    // UnitGenerateOptions.MinMaxMethod\n    public static Hp Min(Hp x, Hp y) =\u003e new Hp(Math.Min(x.value, y.value));\n    public static Hp Max(Hp x, Hp y) =\u003e new Hp(Math.Max(x.value, y.value));\n}\n```\n\nYou can configure with `UnitGenerateOptions`, which method to implement.\n\n```csharp\n[Flags]\nenum UnitGenerateOptions\n{\n    None = 0,\n    ImplicitOperator = 1,\n    ParseMethod = 1 \u003c\u003c 1,\n    MinMaxMethod = 1 \u003c\u003c 2,\n    ArithmeticOperator = 1 \u003c\u003c 3,\n    ValueArithmeticOperator = 1 \u003c\u003c 4,\n    Comparable = 1 \u003c\u003c 5,\n    Validate = 1 \u003c\u003c 6,\n    JsonConverter = 1 \u003c\u003c 7,\n    MessagePackFormatter = 1 \u003c\u003c 8,\n    DapperTypeHandler = 1 \u003c\u003c 9,\n    EntityFrameworkValueConverter = 1 \u003c\u003c 10,\n    WithoutComparisonOperator = 1 \u003c\u003c 11,\n    JsonConverterDictionaryKeySupport = 1 \u003c\u003c 12,\n    Normalize = 1 \u003c\u003c 13,\n}\n```\n\nUnitGenerateOptions has some serializer support. For example, a result like `Serialize(userId) =\u003e { Value = 1111 }` is awful. The value-object should be serialized natively, i.e. `Serialize(useId) =\u003e 1111`, and should be able to be added directly to a database, etc.\n\nCurrently UnitGenerator supports [MessagePack for C#](https://github.com/MessagePack-CSharp/MessagePack-CSharp), System.Text.Json(JsonSerializer), [Dapper](https://github.com/StackExchange/Dapper) and EntityFrameworkCore.\n\n```csharp\n[UnitOf\u003cint\u003e(UnitGenerateOptions.MessagePackFormatter)]\npublic readonly partial struct UserId;\n\n// -- generates\n\n[MessagePackFormatter(typeof(UserIdMessagePackFormatter))]\npublic readonly partial struct UserId \n{\n    class UserIdMessagePackFormatter : IMessagePackFormatter\u003cUserId\u003e\n    {\n        public void Serialize(ref MessagePackWriter writer, UserId value, MessagePackSerializerOptions options)\n        {\n            options.Resolver.GetFormatterWithVerify\u003cint\u003e().Serialize(ref writer, value.value, options);\n        }\n\n        public UserId Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)\n        {\n            return new UserId(options.Resolver.GetFormatterWithVerify\u003cint\u003e().Deserialize(ref reader, options));\n        }\n    }\n}\n```\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n## Table of Contents\n\n- [UnitOfAttribute](#unitofattribute)\n- [UnitGenerateOptions](#unitgenerateoptions)\n  - [ImplicitOperator](#implicitoperator)\n  - [ParseMethod](#parsemethod)\n  - [MinMaxMethod](#minmaxmethod)\n  - [ArithmeticOperator](#arithmeticoperator)\n  - [ValueArithmeticOperator](#valuearithmeticoperator)\n  - [Comparable](#comparable)\n  - [WithoutComparisonOperator](#withoutcomparisonoperator)\n  - [Validate](#validate)\n  - [Normalize](#normalize)\n  - [JsonConverter](#jsonconverter)\n  - [JsonConverterDictionaryKeySupport](#jsonconverterdictionarykeysupport)\n  - [MessagePackFormatter](#messagepackformatter)\n  - [DapperTypeHandler](#dappertypehandler)\n  - [EntityFrameworkValueConverter](#entityframeworkvalueconverter)\n- [Use for Unity](#use-for-unity)\n- [License](#license)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n## UnitOfAttribute\nWhen referring to the UnitGenerator, it generates a internal `UnitOfAttribute`.\n\n```csharp\nnamespace UnitGenerator\n{\n    [AttributeUsage(AttributeTargets.Struct, AllowMultiple = false)]\n    internal class UnitOfAttribute : Attribute\n    {\n        public Type Type { get; }\n        public UnitGenerateOptions Options { get; }\n        public UnitArithmeticOperators ArithmeticOperators { get; set; }\n        public string? ToStringFormat { get; set; }\n        \n        public UnitOfAttribute(Type type, UnitGenerateOptions options = UnitGenerateOptions.None) { ... }\n    }\n\n#if NET7_0_OR_GREATER\n    [AttributeUsage(AttributeTargets.Struct, AllowMultiple = false)]\n    internal class UnitOfAttribute\u003cT\u003e : Attribute\n    {\n        public Type Type { get; }\n        public UnitGenerateOptions Options { get; }\n        public UnitArithmeticOperators ArithmeticOperators { get; set; } = UnitArithmeticOperators.All;\n        public string? ToStringFormat { get; set; }\n\n        public UnitOfAttribute(UnitGenerateOptions options = UnitGenerateOptions.None)\n        {\n            this.Type = typeof(T);\n            this.Options = options;\n        }\n    }\n#endif\n}\n```\n\nYou can attach this attribute with any specified underlying type to `readonly partial struct`.\n\n```csharp\n[UnitOf(typeof(Guid))]\npublic readonly partial struct GroupId { }\n\n[UnitOf(typeof(string))]\npublic readonly partial struct Message { }\n\n[UnitOf(typeof(long))]\npublic readonly partial struct Power { }\n\n[UnitOf(typeof(byte[]))]\npublic readonly partial struct Image { }\n\n[UnitOf(typeof(DateTime))]\npublic readonly partial struct StartDate { }\n\n[UnitOf(typeof((string street, string city)))]\npublic readonly partial struct StreetAddress { }\n```\n\nStandard UnitOf(`UnitGenerateOptions.None`) generates value constructor, `explicit operator`, `implement IEquatable\u003cT\u003e`, `override GetHashCode`, `override ToString`, `==` and `!=` operator, `TypeConverter` for ASP.NET Core binding, `AsPrimitive` method.\n\nIf you want to retrieve primitive value, use `AsPrimitive()` instead of `.Value`. This is intended to avoid casual getting of primitive values (using the arithmetic operator option if available).\n\n\u003e When type is bool, also implements `true`, `false`, `!` operators.\n\n```csharp \npublic static bool operator true(Foo x) =\u003e x.value;\npublic static bool operator false(Foo x) =\u003e !x.value;\npublic static bool operator !(Foo x) =\u003e !x.value;\n```\n\n\u003e When type is Guid or [Ulid](https://github.com/Cysharp/Ulid), also implements `New()` and `New***()` static operator.\u003cbr /\u003e\n\u003e For Guid type in .NET 9.0 or later, these methods accept an optional `uuidV7` parameter. When `uuidV7` is set to `true`, the methods use `Guid.CreateVersion7()` internally.\n\n```csharp\npublic static GroupId New();\npublic static GroupId NewGroupId();\n// overload .NET 9.0+\npublic static GroupId New(bool uuidV7);\npublic static GroupId NewGroupId(bool uuidV7);\n```\n\nSecond parameter `UnitGenerateOptions options` can configure which method to implement, default is `None`.\n\nOptional named parameter: `ArithmeticOperators` can configure which generates operators specifically. Default is `Number`. (This can be used if UnitGenerateOptions.ArithmeticOperator is specified.)\n\nOptional named parameter: `ToStringFormat` can configure `ToString` format. Default is null and output as $`{0}`.\n\n## UnitGenerateOptions\n\nWhen referring to the UnitGenerator, it generates a internal `UnitGenerateOptions` that is bit flag of which method to implement.\n\n```csharp\n[Flags]\ninternal enum UnitGenerateOptions\n{\n    None = 0,\n    ImplicitOperator = 1,\n    ParseMethod = 2,\n    MinMaxMethod = 4,\n    ArithmeticOperator = 8,\n    ValueArithmeticOperator = 16,\n    Comparable = 32,\n    Validate = 64,\n    JsonConverter = 128,\n    MessagePackFormatter = 256,\n    DapperTypeHandler = 512,\n    EntityFrameworkValueConverter = 1024,\n}\n```\n\nYou can use this with `[UnitOf]`.\n\n```csharp\n[UnitOf(typeof(int), UnitGenerateOptions.ArithmeticOperator | UnitGenerateOptions.ValueArithmeticOperator | UnitGenerateOptions.Comparable | UnitGenerateOptions.MinMaxMethod)]\npublic readonly partial struct Strength { }\n\n[UnitOf(typeof(DateTime), UnitGenerateOptions.Validate | UnitGenerateOptions.ParseMethod | UnitGenerateOptions.Comparable)]\npublic readonly partial struct EndDate { }\n\n[UnitOf(typeof(double), UnitGenerateOptions.ParseMethod | UnitGenerateOptions.MinMaxMethod | UnitGenerateOptions.ArithmeticOperator | UnitGenerateOptions.ValueArithmeticOperator | UnitGenerateOptions.Comparable | UnitGenerateOptions.Validate | UnitGenerateOptions.JsonConverter | UnitGenerateOptions.MessagePackFormatter | UnitGenerateOptions.DapperTypeHandler | UnitGenerateOptions.EntityFrameworkValueConverter)]\npublic readonly partial struct AllOptionsStruct { }\n```\n\nYou can setup project default options like this.\n\n```csharp\ninternal static class UnitOfOptions\n{\n    public const UnitGenerateOptions Default = UnitGenerateOptions.ArithmeticOperator | UnitGenerateOptions.ValueArithmeticOperator | UnitGenerateOptions.Comparable | UnitGenerateOptions.MinMaxMethod;\n}\n\n[UnitOf(typeof(int), UnitOfOptions.Default)]\npublic readonly partial struct Hp { }\n```\n\n### ImplicitOperator\n\n```csharp\n// Default\npublic static explicit operator U(T value) =\u003e value.value;\npublic static explicit operator T(U value) =\u003e new T(value);\n\n// UnitGenerateOptions.ImplicitOperator\npublic static implicit operator U(T value) =\u003e value.value;\npublic static implicit operator T(U value) =\u003e new T(value);\n```\n\n### ParseMethod \n\n```csharp\npublic static T Parse(string s)\npublic static bool TryParse(string s, out T result)\n```\n\n### MinMaxMethod\n\n```csharp\npublic static T Min(T x, T y)\npublic static T Max(T x, T y)\n```\n\n### ArithmeticOperator\n\n```csharp\npublic static T operator +(in T x, in T y) =\u003e new T(checked((U)(x.value + y.value)));\npublic static T operator -(in T x, in T y) =\u003e new T(checked((U)(x.value - y.value)));\npublic static T operator *(in T x, in T y) =\u003e new T(checked((U)(x.value * y.value)));\npublic static T operator /(in T x, in T y) =\u003e new T(checked((U)(x.value / y.value)));\npublic static T operator +(T value) =\u003e new((U)(+value.value));\npublic static T operator -(T value) =\u003e new((U)(-value.value));\npublic static T operator ++(T x) =\u003e new T(checked((U)(x.value + 1)));\npublic static T operator --(T x) =\u003e new T(checked((U)(x.value - 1)));\n```\n\nIn addition,  all members conforming to [System.Numerics.INumber\u003cT\u003e](https://learn.microsoft.com/ja-jp/dotnet/api/system.numerics.inumber-1) are generated.\n\nIf you want to suppress this and generate only certain operators, you can use the the `ArithmeticOperatros` option of `[UnitOf]` attribute as follows:\n\n```csharp\n[UnitOf(\n    typeof(int), \n    UnitGenerateOptions.ArithmeticOperator,\n    ArithmeticOperators = UnitArithmeticOperators.Addition | UnitArithmeticOperators.Subtraction)]\npublic readonly partial struct Hp { }\n```\n\n| Value                               | Generates                                                                              | \n|-------------------------------------|----------------------------------------------------------------------------------------|\n| UnitArithmeticOperators.Addition    | `T operator +(T, T)`                                            |\n| UnitArithmeticOperators.Subtraction | `T operator -(T, T)`                                             |\n| UnitArithmeticOperators.Multiply    | `T operator *(T, T)`,  `T operator +(T)`, `T operator-(T)` |\n| UnitArithmeticOperators.Division    | `T operator /(T, T)`,  `T operator +(T)`, `T operator-(T)` |\n| UnitArithmeticOperators.Increment   | `T operator ++(T)`                                                                     |\n| UnitArithmeticOperators.Decrement   | `T operator --(T)`                                                                     |\n\n### ValueArithmeticOperator\n\n```csharp\npublic static T operator +(in T x, in U y) =\u003e new T(checked((U)(x.value + y)));\npublic static T operator -(in T x, in U y) =\u003e new T(checked((U)(x.value - y)));\npublic static T operator *(in T x, in U y) =\u003e new T(checked((U)(x.value * y)));\npublic static T operator /(in T x, in U y) =\u003e new T(checked((U)(x.value / y)));\n```\n\n### Comparable\n\nImplements `IComparable\u003cT\u003e` and `\u003e`, `\u003c`, `\u003e=`, `\u003c=` operators.\n\n```csharp\npublic U CompareTo(T other) =\u003e value.CompareTo(other.value);\npublic static bool operator \u003e(in T x, in T y) =\u003e x.value \u003e y.value;\npublic static bool operator \u003c(in T x, in T y) =\u003e x.value \u003c y.value;\npublic static bool operator \u003e=(in T x, in T y) =\u003e x.value \u003e= y.value;\npublic static bool operator \u003c=(in T x, in T y) =\u003e x.value \u003c= y.value;\n```\n\n### WithoutComparisonOperator\n\nWithout implements `\u003e`, `\u003c`, `\u003e=`, `\u003c=` operators. For example, useful for Guid.\n\n```csharp\n[UnitOf(typeof(Guid), UnitGenerateOptions.Comparable | UnitGenerateOptions.WithoutComparisonOperator)]\npublic readonly partial struct FooId { }\n```\n\n### Validate\n\nImplements `partial void Validate()` method that is called on constructor.\n\n```csharp\n// You can implement this custom validate method.\n[UnitOf(typeof(int), UnitGenerateOptions.Validate)]\npublic readonly partial struct SampleValidate\n{\n    // impl here.\n    private partial void Validate()\n    {\n        if (value \u003e 9999) throw new Exception(\"Invalid value range: \" + value);\n    }\n}\n\n// Source generator generate this codes.\npublic T(int value)\n{\n    this.value = value;\n    this.Validate();\n}\n \nprivate partial void Validate();\n```\n\n### Normalize\n\nImplements `partial void Normalize(ref T value)` method that is called on constructor.\n\n```csharp\n// You can implement this custom normalize method to change value during initialization\n[UnitOf(typeof(int), UnitGenerateOptions.Normalize)]\npublic readonly partial struct SampleValidate\n{\n    // impl here.\n    private partial void Normalize(ref int value)\n    {\n        value = Math.Max(value, 9999);\n    }\n}\n\n// Source generator generate this codes.\npublic T(int value)\n{\n    this.value = value;\n    this.Normalize(ref this.value);\n}\n \nprivate partial void Normalize(ref int value);\n```\n\n### JsonConverter\n\nImplements `System.Text.Json`'s `JsonConverter`. It will be used `JsonSerializer` automatically.\n\n```csharp\n[JsonConverter(typeof(UserIdJsonConverter))]\npublic readonly partial struct UserId\n{\n    class UserIdJsonConverter : JsonConverter\u003cUserId\u003e\n}\n```\n\n### JsonConverterDictionaryKeySupport\n\nImplements `JsonConverter`'s `WriteAsPropertyName/ReadAsPropertyName`. It supports from .NET 6, supports Dictionary's Key.\n\n```csharp\nvar dict = Dictionary\u003cUserId, int\u003e\nJsonSerializer.Serialize(dict);\n````\n\n### MessagePackFormatter\n\nImplements MessagePack for C#'s `MessagePackFormatter`. It will be used `MessagePackSerializer` automatically.\n\n```csharp\n[MessagePackFormatter(typeof(UserIdMessagePackFormatter))]\npublic readonly partial struct UserId\n{\n    class UserIdMessagePackFormatter : IMessagePackFormatter\u003cUserId\u003e\n}\n```\n\n### DapperTypeHandler\n\nImplements Dapper's TypeHandler by public accessibility. TypeHandler is automatically registered at the time of Module initialization.\n\n```csharp\npublic readonly partial struct UserId\n{\n    public class UserIdTypeHandler : Dapper.SqlMapper.TypeHandler\u003cUserId\u003e\n}\n\n[ModuleInitializer]\npublic static void AddTypeHandler()\n{\n    Dapper.SqlMapper.AddTypeHandler(new A.ATypeHandler());\n}\n```\n\n### EntityFrameworkValueConverter\n\nImplements EntityFrameworkCore's ValueConverter by public accessibility. It is not registered automatically so you need to register manually.\n\n```csharp\npublic readonly partial struct UserId\n{\n    public class UserIdValueConverter : ValueConverter\u003cUserId, int\u003e\n}\n\n// setup handler manually\nbuilder.HasConversion(new UserId.UserIdValueConverter());\n```\n\n## Use for Unity\n\nMinimum supported Unity version is `2022.3.12f1`.\n\nThe easiest way is to install `UnitGenerator` from NuGet using [NuGetForUnity](https://github.com/GlitchEnzo/NuGetForUnity).\n\nAlternatively, you can download `UnitGenerator.dll` from the [releases page](https://github.com/Cysharp/UnitGenerator/releases) page and set it up as a `RoslynAnalyzer` to make it work.\n\nLicense\n---\nThis library is under the MIT License.\n","funding_links":[],"categories":["Content","C#"],"sub_categories":["76. [UnitGenerator](https://ignatandrei.github.io/RSCG_Examples/v2/docs/UnitGenerator) , in the [PrimitiveObsession](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#primitiveobsession) category"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCysharp%2FUnitGenerator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FCysharp%2FUnitGenerator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCysharp%2FUnitGenerator/lists"}