{"id":23443466,"url":"https://github.com/r-koubou/valueobjectgenerator","last_synced_at":"2026-03-04T10:31:21.304Z","repository":{"id":44900611,"uuid":"330274918","full_name":"r-koubou/ValueObjectGenerator","owner":"r-koubou","description":"Generating code of value object by C# 9.0 Source Generator","archived":false,"fork":false,"pushed_at":"2022-01-19T19:09:09.000Z","size":168,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-10T05:44:31.652Z","etag":null,"topics":["csharp","dotnet","nuget","roslyn","source-generation"],"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/r-koubou.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}},"created_at":"2021-01-16T23:04:38.000Z","updated_at":"2025-02-06T04:37:46.000Z","dependencies_parsed_at":"2022-09-16T03:41:19.841Z","dependency_job_id":null,"html_url":"https://github.com/r-koubou/ValueObjectGenerator","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/r-koubou/ValueObjectGenerator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r-koubou%2FValueObjectGenerator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r-koubou%2FValueObjectGenerator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r-koubou%2FValueObjectGenerator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r-koubou%2FValueObjectGenerator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/r-koubou","download_url":"https://codeload.github.com/r-koubou/ValueObjectGenerator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r-koubou%2FValueObjectGenerator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279653226,"owners_count":26205751,"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","status":"online","status_checked_at":"2025-10-18T02:00:06.492Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["csharp","dotnet","nuget","roslyn","source-generation"],"created_at":"2024-12-23T18:19:32.090Z","updated_at":"2025-10-19T00:38:53.822Z","avatar_url":"https://github.com/r-koubou.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ValueObject Generator\n\nGenerating code of value object by C# 9.0 [Source Generator](https://devblogs.microsoft.com/dotnet/introducing-c-source-generators/)\n\nSimple value objects can be created.\n\n\n\n## Example\n\n```c#\n[ValueObject(typeof(int))]\npublic partial class Sample // 'struct' also supporting\n{\n    // By default, the Validate method is defined and called from constructor\n    // If ValueOption.NonValidating is set, Validate method will not be defined\n    private static partial int Validate( int value ) =\u003e value;\n}\n```\n\nwill be generated to following\n\n```c#\nusing System;\nusing System.Diagnostics.CodeAnalysis;\n\npublic partial struct Sample : IEquatable\u003cSample\u003e\n{\n    public int Value { get; }\n\n    public Sample( int value )\n    {\n        Value = Validate( value );\n    }\n\n    private static partial int Validate( int value );\n\n    //\n    // Default ToString()\n    //\n    public override string ToString()\n    {\n        return Value.ToString() ?? \"\";\n    }\n\n    //----------------------------------------------------------------------\n    // Equality\n    //----------------------------------------------------------------------\n    public bool Equals( Sample other )\n    {\n        return Equals( Value, other.Value );\n    }\n\n    public override bool Equals( [AllowNull] object obj )\n    {\n        return obj is Sample other \u0026\u0026 Equals( other );\n    }\n\n    // HashCode\n    public override int GetHashCode() =\u003e Value.GetHashCode();\n\n    // Operator ==, !=\n    public static bool operator ==( Sample a, Sample b )\n    {\n        return a.Equals( b );\n    }\n\n    public static bool operator !=( Sample a, Sample b )\n    {\n        return !( a == b );\n    }\n}\n```\n\n\n\n------\n\n\n\n## ValueObject Attribute\n\n`[ValueObject \u003ctype\u003e, [ValueName], [Option] ]`\n\n### Type (*Required)\n\nType of value. use typeof syntax.\n\n### ValueName\n\nApplied to variable name (default: \"Value\")\n\ne.g.\n\n```c#\n// Explicitly set the name of the value variable\n[ValueObject(typeof(int), ValueName =\"Point\")]\npublic partial class Hp {}\n```\n\nwill be generated to following\n\n```c#\npublic partial class Hp : IEquatable\u003cHp\u003e\n{\n    public int Point { get; } // variable name will be \"Point\" (default: \"Value\")\n}\n```\n\n\n\n### Option\n\nFlags to specify additional value specifications.\n\nif set an`OptionFlags` value to ValueObjectAttribute, Generate code according to the flag value\n\n### NonValidating\n\n- Don't genetate `Valid` method\n- Don't validate in constructor\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\u003cdiv\u003e\n\n```c#\n[ValueObject( typeof(int), Option = ValueOption.NonValidating)]\npublic partial class Sample {}\n\n// *Validate method will not be defined\n// private static partial int Validate( int value );\n```\n\n\u003c/div\u003e\u003c/details\u003e\n\n### Explicit\n\nAdd explicit operator\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\u003cdiv\u003e\n\n```c#\n[ValueObject( typeof(int), Option = ValueOption.Explicit )]\npublic partial class Sample {}\n```\n\nwill be generated to following\n\n```c#\npublic static explicit operator int( Sample x )\n{\n    return x.Value;\n}\n\npublic static explicit operator Sample( int value )\n{\n    return new Sample( value );\n}\n```\n\u003c/div\u003e\u003c/details\u003e\n\n### Implicit\n\nAdd  implicit operator\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\u003cdiv\u003e\n\n```c#\n[ValueObject( typeof(int), Option = ValueOption.Implicit )]\npublic partial class Sample {}\n```\n\nwill be generated to following\n\n```c#\npublic static implicit operator int( Sample x )\n{\n    return x.Value;\n}\n\npublic static implicit operator Sample( int value )\n{\n    return new Sample( value );\n}\n```\n\n\u003c/div\u003e\u003c/details\u003e\n\n### Comparable\n\nAdd  IComparable\\\u003cT\\\u003e implementation\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\u003cdiv\u003e\n\n```c#\n[ValueObject( typeof(int), Option = ValueOption.Implicit )]\npublic partial class Sample {}\n```\n\nwill be generated to following\n\n```c#\npublic int CompareTo( Sample other )\n{\n    if( ReferenceEquals( this, other ) )\n    {\n        return 0;\n    }\n\n    if( ReferenceEquals( null, other ) )\n    {\n        return 1;\n    }\n\n    return Value.CompareTo( other.Value );\n}\n```\n\n\u003c/div\u003e\u003c/details\u003e\n\n### ToString\n\nAdd ToStringImpl Method for custom ToString implementarion\n\n#### Default\n\n```c#\npublic override string ToString()\n{\n    return Value.ToString() ?? \"\";\n}\n```\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\u003cdiv\u003e\n\n```c#\n[ValueObject( typeof(int), Option = ValueOption.ToString )]\npublic partial class Sample {}\n```\n\nwill be generated to following\n\n```c#\nprivate partial string ToStringImpl();\n\npublic override string ToString()\n{\n    return ToStringImpl();\n}\n```\n\nDefault\n\n```c#\npublic override string ToString()\n{\n    return Value.ToString() ?? \"\";\n}\n```\n\n\u003c/div\u003e\u003c/details\u003e\n\n------\n\n## Available other attribute\n\nProvides presets for validation. In many cases, it is exclusive to the Validate method.\n\n### Value range\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\u003cdiv\u003e\n\n```c#\n[ValueObject(typeof(int))]\n// Set an explicit range of values\n[ValueRange(0, 9999)]\npublic partial class Count {}\n```\n\nwill be generated to following\n\n```c#\npublic partial class Count : IEquatable\u003cCount\u003e\n{\n    public int Value { get; }\n\n    public Count( int value )\n    {\n        if( value \u003c (0) || value \u003e (9999) )\n        {\n            throw new ArgumentOutOfRangeException( $\"(Count) Out of range : {value} (range:0 \u003c 9999)\" );\n        }\n        Value = value;\n    }\n  :\n  :\n}\n```\n\n\u003c/div\u003e\u003c/details\u003e\n\n### Not negative\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\u003cdiv\u003e\n\n```c#\n[ValueObject(typeof(int))]\n[NotNegative]\npublic partial class Count {}\n```\n\nwill be generated to following\n\n```c#\npublic partial class Count : IEquatable\u003cCount\u003e\n{\n    public int Value { get; }\n\n    public Count( int value )\n    {\n        if( value \u003c 0 )\n        {\n            throw new ArgumentException( $\"(Count) value is negative : {value}\" );\n        }\n        Value = value;\n    }\n  :\n  :\n}\n```\n\n\u003c/div\u003e\u003c/details\u003e\n\n### Not empty\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\u003cdiv\u003e\n\n```c#\n[ValueObject(typeof(string))]\n[NotEmpty]\npublic partial class Name {}\n```\n\nwill be generated to following\n\n\n```c#\npublic partial class Name : IEquatable\u003cName\u003e\n{\n    public string Value { get; }\n\n    public Name( string value )\n    {\n        if( string.IsNullOrEmpty( value ) || value.Trim().Length == 0 )\n        {\n            throw new ArgumentException( $\"(Name) value is empty\" );\n        }\n        Value = value;\n    }\n}\n```\n\nNote: if type is string, use string.IsNullOrEmpty, Trim. Otherwise use Linq.Any()\n\ne.g.\n\n```c#\n[ValueObject(typeof(string[]))]\n[NotEmpty]\npublic partial class Names {}\n```\n\nwill be generated to following\n\n```c#\npublic partial class Names : IEquatable\u003cNames\u003e\n{\n    public string[] Value { get; }\n\n    public Names( string[] value )\n    {\n        if( !value.Any() )\n        {\n            throw new ArgumentException( $\"(Names) value is empty\" );\n        }\n        Value = value;\n    }\n  :\n  :\n}\n```\n\nIf you do not want to treat a string with only whitespace characters as Empty, set the **ExcludeWhiteSpace** argument to true.\n\n```c#\n[ValueObject(typeof(string))]\n[NotEmpty(ExcludeWhiteSpace=true)]\npublic partial class Name {}\n```\n\nwill be generated to following\n\n```c#\npublic partial class Name : IEquatable\u003cName\u003e\n{\n    public string Value { get; }\n\n    public Name( string value )\n    {\n        if( string.IsNullOrEmpty( value ) )\n        {\n            throw new ArgumentException( $\"(Name) value is empty\" );\n        }\n        Value = value;\n    }\n  :\n  :\n}\n```\n\n\u003c/div\u003e\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fr-koubou%2Fvalueobjectgenerator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fr-koubou%2Fvalueobjectgenerator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fr-koubou%2Fvalueobjectgenerator/lists"}