Install
| Product | Versions |
|---|---|
| .NET | |
| .NET Standard |
README
Meziantou.Framework.StronglyTypedId
The source generator generates constructors, properties, equality members, common interfaces, converters for multiple serializers
[StronglyTypedId<int>]
public partial struct ProjectId { }
or using typeof if you're not using a version of C# that supports generic attributes
[StronglyTypedId(typeof(int))]
public partial struct ProjectId { }
StronglyTypedId generates the following code:
[System.ComponentModel.TypeConverterAttribute(typeof(ProjectIdTypeConverter))]
[System.Text.Json.Serialization.JsonConverterAttribute(typeof(ProjectIdJsonConverter))]
[Newtonsoft.Json.JsonConverterAttribute(typeof(ProjectIdNewtonsoftJsonConverter))]
[MongoDB.Bson.Serialization.Attributes.BsonSerializerAttribute(typeof(ProjectIdBsonConverter))]
public partial struct ProjectId :
System.IEquatable<ProjectId>,
System.IParsable<ProjectId>, // .NET 7+
System.ISpanParsable<ProjectId>, // .NET 7+
IStronglyTypedId, // When Meziantou.Framework.StronglyTypedId.Interfaces is referenced
IStronglyTypedId<int>, // When Meziantou.Framework.StronglyTypedId.Interfaces is referenced
IComparable, IComparable<ProjectId> // When at least one of the interface is explicitly defined by the user
{
public int Value { get; }
public string ValueAsString { get; } // Value formatted using InvariantCulture
private ProjectId(int value);
public static ProjectId FromInt32(int value);
public static ProjectId Parse(string value);
public static ProjectId Parse(ReadOnlySpan<char> value);
public static bool TryParse(string value, out ProjectId result);
public static bool TryParse(ReadOnlySpan<char> value, out ProjectId result);
public override int GetHashCode();
public override bool Equals(object? other);
public bool Equals(ProjectId other);
public static bool operator ==(ProjectId a, ProjectId b);
public static bool operator !=(ProjectId a, ProjectId b);
public override string ToString();
private partial class ProjectIdTypeConverter : System.ComponentModel.TypeConverter
{
public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType);
public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value);
public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type destinationType);
public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType);
}
// Generated only when System.Text.Json is accessible
private partial class ProjectIdJsonConverter : System.Text.Json.Serialization.JsonConverter<ProjectId>
{
public override void Write(System.Text.Json.Utf8JsonWriter writer, ProjectId value, System.Text.Json.JsonSerializerOptions options);
public override ProjectId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options);
}
// Generated only when Newtonsoft.Json is accessible
private partial class ProjectIdNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter
{
public override bool CanRead { get; }
public override bool CanWrite { get; }
public override bool CanConvert(System.Type type);
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object? value, Newtonsoft.Json.JsonSerializer serializer);
public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object? existingValue, Newtonsoft.Json.JsonSerializer serializer);
}
// Generated only when MongoDB.Bson.Serialization.Serializers.SerializerBase is accessible
private partial class ProjectIdBsonConverter : MongoDB.Bson.Serialization.Serializers.SerializerBase<ProjectId>
{
public override ProjectId Deserialize(MongoDB.Bson.Serialization.BsonDeserializationContext context, MongoDB.Bson.Serialization.BsonDeserializationArgs args);
public override void Serialize(MongoDB.Bson.Serialization.BsonSerializationContext context, MongoDB.Bson.Serialization.BsonSerializationArgs args, ProjectId value);
}
}
If the Meziantou.Framework.StronglyTypedId.Interfaces NuGet package is present, the generator will implements IStronglyTypedId and IStronglyTypedId.
Supported types
System.BooleanSystem.ByteSystem.DateTimeSystem.DateTimeOffsetSystem.DecimalSystem.DoubleSystem.GuidSystem.HalfSystem.Int16System.Int32System.Int64System.Int128System.Numerics.BigIntegerSystem.SByteSystem.SingleSystem.StringSystem.Uint16System.Uint32System.Uint64System.Uint128MongoDB.Bson.ObjectId
Configuration
You can configure the code generation using the [StronglyTypedIdAttribute] attribute:
[StronglyTypedId(idType: typeof(long),
generateSystemTextJsonConverter: true,
generateNewtonsoftJsonConverter: true,
generateSystemComponentModelTypeConverter: true,
generateMongoDBBsonSerialization: true,
addCodeGeneratedAttribute: true
)]
public partial struct ProjectId { }
When the underlying type is System.Guid, you can choose how the generated New() method creates the value. The default is Version4 (Guid.NewGuid()). Version7 (Guid.CreateVersion7()) requires .NET 9 or later, otherwise the MFSTID0002 diagnostic is reported. None doesn't generate the New() method. The option only applies to System.Guid; using it with another underlying type reports the MFSTID0003 diagnostic:
[StronglyTypedId<Guid>(GuidGenerationStrategy = GuidGenerationStrategy.Version7)]
public partial struct ProjectId { }
// Generated by the source generator
public partial struct ProjectId
{
public static ProjectId New() => new ProjectId(Guid.CreateVersion7());
}
[StronglyTypedId<Guid>(GuidGenerationStrategy = GuidGenerationStrategy.None)]
public partial struct ProjectId { } // No New() method is generated
You can configure the default value of the options for all the types of an assembly using the [assembly: StronglyTypedIdDefaults] attribute. Options set on [StronglyTypedId] take precedence over the assembly-level defaults:
[assembly: StronglyTypedIdDefaults(GuidGenerationStrategy = GuidGenerationStrategy.Version7,
GenerateNewtonsoftJsonConverter = false,
GenerateMongoDBBsonSerialization = false,
GenerateSystemComponentModelTypeConverter = false,
GenerateSystemTextJsonConverter = true,
AddCodeGeneratedAttribute = true,
StringComparison = StringComparison.Ordinal,
GenerateToStringAsRecord = true)]
[StronglyTypedId<Guid>]
public partial struct ProjectId { } // New() uses Guid.CreateVersion7()
[StronglyTypedId<Guid>(GuidGenerationStrategy = GuidGenerationStrategy.Version4)]
public partial struct CustomerId { } // New() uses Guid.NewGuid()
You can generate IComparable, IComparable and comparison operators by adding one interface:
[StronglyTypedId<int>]
public partial struct ProjectId : IComparable { }
// Generated by the source generator
public partial struct ProjectId : IComparable<ProjectId>
{
public int CompareTo(object? other);
public int CompareTo(ProjectId other);
public static bool operator <(ProjectId left, ProjectId right);
public static bool operator <=(ProjectId left, ProjectId right);
public static bool operator >(ProjectId left, ProjectId right);
public static bool operator >=(ProjectId left, ProjectId right);
}
Additional resources
Analyzer rules
| Id | Category | Description | Severity | Enabled |
|---|---|---|---|---|
MFSTID0001 |
StronglyTypedId | Not supported type | Error | ✔️ |
MFSTID0002 |
StronglyTypedId | Guid generation strategy is not supported by the target framework | Error | ✔️ |
MFSTID0003 |
StronglyTypedId | Guid generation strategy is only applicable to Guid | Warning | ✔️ |
MFSTID0004 |
StronglyTypedId | Generic types are not supported | Error | ✔️ |
Changes from Previous Version
Adoption Assessment
A verified publisher signal is available. Assess fit from the package's supported frameworks, license and dependency graph rather than popularity alone.
Related Guides & Workflows
Learn how to evaluate, integrate, or audit this package in your .NET project.