Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added MongoSerializer and Mongo ObjectId backing type #62

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
  •  
  •  
  •  
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ public enum StronglyTypedIdBackingType
Long = 4,
NullableString = 5,
MassTransitNewId = 6,
ObjectId = 7
}
}
5 changes: 5 additions & 0 deletions src/StronglyTypedIds.Attributes/StronglyTypedIdConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,10 @@ public enum StronglyTypedIdConverter
/// Creates a Dapper TypeHandler for converting to and from the type
/// </summary>
DapperTypeHandler = 32,

/// <summary>
/// Creates a Mongo Serializer for converting string to and from type
/// </summary>
MongoSerializer = 64,
}
}
23 changes: 23 additions & 0 deletions src/StronglyTypedIds/EmbeddedSources.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ internal static class EmbeddedSources
LoadEmbeddedResource("StronglyTypedIds.Templates.Guid.Guid_EfCoreValueConverter.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.Guid.Guid_DapperTypeHandler.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.Guid.Guid_IComparable.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.Guid.Guid_MongoSerializer.cs"),
false
);

Expand All @@ -37,6 +38,7 @@ internal static class EmbeddedSources
LoadEmbeddedResource("StronglyTypedIds.Templates.Int.Int_EfCoreValueConverter.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.Int.Int_DapperTypeHandler.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.Int.Int_IComparable.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.Int.Int_MongoSerializer.cs"),
false
);

Expand All @@ -49,6 +51,7 @@ internal static class EmbeddedSources
LoadEmbeddedResource("StronglyTypedIds.Templates.Long.Long_EfCoreValueConverter.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.Long.Long_DapperTypeHandler.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.Long.Long_IComparable.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.Long.Long_MongoSerializer.cs"),
false
);

Expand All @@ -61,6 +64,7 @@ internal static class EmbeddedSources
LoadEmbeddedResource("StronglyTypedIds.Templates.String.String_EfCoreValueConverter.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.String.String_DapperTypeHandler.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.String.String_IComparable.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.String.String_MongoSerializer.cs"),
false
);

Expand All @@ -73,6 +77,7 @@ internal static class EmbeddedSources
LoadEmbeddedResource("StronglyTypedIds.Templates.NullableString.NullableString_EfCoreValueConverter.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.NullableString.NullableString_DapperTypeHandler.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.NullableString.NullableString_IComparable.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.NullableString.NullableString_MongoSerializer.cs"),
true
);

Expand All @@ -85,12 +90,27 @@ internal static class EmbeddedSources
LoadEmbeddedResource("StronglyTypedIds.Templates.NewId.NewId_EfCoreValueConverter.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.NewId.NewId_DapperTypeHandler.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.NewId.NewId_IComparable.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.NewId.NewId_MongoSerializer.cs"),
false
);

internal static readonly ResourceCollection ObjectIdResources = new(
AutoGeneratedHeader,
LoadEmbeddedResource("StronglyTypedIds.Templates.ObjectId.ObjectId_Base.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.ObjectId.ObjectId_NewtonsoftJsonConverter.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.ObjectId.ObjectId_SystemTextJsonConverter.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.ObjectId.ObjectId_TypeConverter.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.ObjectId.ObjectId_EfCoreValueConverter.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.ObjectId.ObjectId_DapperTypeHandler.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.ObjectId.ObjectId_IComparable.cs"),
LoadEmbeddedResource("StronglyTypedIds.Templates.ObjectId.ObjectId_MongoSerializer.cs"),
false
);

internal const string TypeConverterAttributeSource = " [System.ComponentModel.TypeConverter(typeof(TESTIDTypeConverter))]";
internal const string NewtonsoftJsonAttributeSource = " [Newtonsoft.Json.JsonConverter(typeof(TESTIDNewtonsoftJsonConverter))]";
internal const string SystemTextJsonAttributeSource = " [System.Text.Json.Serialization.JsonConverter(typeof(TESTIDSystemTextJsonConverter))]";
internal const string MongoSerializerAttributeSource = " [MongoDB.Bson.Serialization.Attributes.BsonSerializer(typeof(TESTIDMongoSerializer))]";

internal static string LoadEmbeddedResource(string resourceName)
{
Expand All @@ -116,6 +136,7 @@ public readonly struct ResourceCollection
public string TypeConverter { get; }
public string EfCoreValueConverter { get; }
public string DapperTypeHandler { get; }
public string Mongo { get; }
public string Comparable { get; }

public ResourceCollection(
Expand All @@ -127,6 +148,7 @@ public ResourceCollection(
string efCoreValueConverter,
string dapperTypeHandler,
string comparable,
string mongo,
bool nullableEnable)
{
BaseId = baseId;
Expand All @@ -137,6 +159,7 @@ public ResourceCollection(
DapperTypeHandler = dapperTypeHandler;
Comparable = comparable;
NullableEnable = nullableEnable;
Mongo = mongo;
Header = header;
}
}
Expand Down
12 changes: 12 additions & 0 deletions src/StronglyTypedIds/SourceGenerationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public static string CreateId(
StronglyTypedIdBackingType.String => EmbeddedSources.StringResources,
StronglyTypedIdBackingType.NullableString => EmbeddedSources.NullableStringResources,
StronglyTypedIdBackingType.MassTransitNewId => EmbeddedSources.NewIdResources,
StronglyTypedIdBackingType.ObjectId => EmbeddedSources.ObjectIdResources,
_ => throw new ArgumentException("Unknown backing type: " + backingType, nameof(backingType)),
};

Expand Down Expand Up @@ -69,6 +70,7 @@ static string CreateId(
var useSystemTextJson = converters.IsSet(StronglyTypedIdConverter.SystemTextJson);
var useEfCoreValueConverter = converters.IsSet(StronglyTypedIdConverter.EfCoreValueConverter);
var useDapperTypeHandler = converters.IsSet(StronglyTypedIdConverter.DapperTypeHandler);
var useMongoSerializer = converters.IsSet(StronglyTypedIdConverter.MongoSerializer);

var useIEquatable = implementations.IsSet(StronglyTypedIdImplementations.IEquatable);
var useIComparable = implementations.IsSet(StronglyTypedIdImplementations.IComparable);
Expand Down Expand Up @@ -121,6 +123,11 @@ static string CreateId(
{
sb.AppendLine(EmbeddedSources.TypeConverterAttributeSource);
}

if (useMongoSerializer)
{
sb.AppendLine(EmbeddedSources.MongoSerializerAttributeSource);
}

sb.Append(resources.BaseId);
ReplaceInterfaces(sb, useIEquatable, useIComparable);
Expand Down Expand Up @@ -156,6 +163,11 @@ static string CreateId(
{
sb.AppendLine(resources.SystemTextJson);
}

if (useMongoSerializer)
{
sb.AppendLine(resources.Mongo);
}

sb.Replace("TESTID", idName);
sb.AppendLine(@" }");
Expand Down
12 changes: 12 additions & 0 deletions src/StronglyTypedIds/Templates/Guid/Guid_MongoSerializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
 class TESTIDMongoSerializer : MongoDB.Bson.Serialization.Serializers.SerializerBase<TESTID>
{
public override TESTID Deserialize(MongoDB.Bson.Serialization.BsonDeserializationContext context, MongoDB.Bson.Serialization.BsonDeserializationArgs args)
{
return new TESTID(new System.Guid(context.Reader.ReadString()));
}

public override void Serialize(MongoDB.Bson.Serialization.BsonSerializationContext context, MongoDB.Bson.Serialization.BsonSerializationArgs args, TESTID value)
{
context.Writer.WriteString(value.Value.ToString());
}
}
12 changes: 12 additions & 0 deletions src/StronglyTypedIds/Templates/Int/Int_MongoSerializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
 class TESTIDMongoSerializer : MongoDB.Bson.Serialization.Serializers.SerializerBase<TESTID>
{
public override TESTID Deserialize(MongoDB.Bson.Serialization.BsonDeserializationContext context, MongoDB.Bson.Serialization.BsonDeserializationArgs args)
{
return new TESTID(context.Reader.ReadInt32());
}

public override void Serialize(MongoDB.Bson.Serialization.BsonSerializationContext context, MongoDB.Bson.Serialization.BsonSerializationArgs args, TESTID value)
{
context.Writer.WriteInt32(value.Value);
}
}
12 changes: 12 additions & 0 deletions src/StronglyTypedIds/Templates/Long/Long_MongoSerializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
 class TESTIDMongoSerializer : MongoDB.Bson.Serialization.Serializers.SerializerBase<TESTID>
{
public override TESTID Deserialize(MongoDB.Bson.Serialization.BsonDeserializationContext context, MongoDB.Bson.Serialization.BsonDeserializationArgs args)
{
return new TESTID(context.Reader.ReadInt64());
}

public override void Serialize(MongoDB.Bson.Serialization.BsonSerializationContext context, MongoDB.Bson.Serialization.BsonSerializationArgs args, TESTID value)
{
context.Writer.WriteInt64(value.Value);
}
}
12 changes: 12 additions & 0 deletions src/StronglyTypedIds/Templates/NewId/NewId_MongoSerializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
 class TESTIDMongoSerializer : MongoDB.Bson.Serialization.Serializers.SerializerBase<TESTID>
{
public override TESTID Deserialize(MongoDB.Bson.Serialization.BsonDeserializationContext context, MongoDB.Bson.Serialization.BsonDeserializationArgs args)
{
return new TESTID(new MassTransit.NewId(context.Reader.ReadString()));
}

public override void Serialize(MongoDB.Bson.Serialization.BsonSerializationContext context, MongoDB.Bson.Serialization.BsonSerializationArgs args, TESTID value)
{
context.Writer.WriteString(value.Value.ToString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
 class TESTIDMongoSerializer : MongoDB.Bson.Serialization.Serializers.SerializerBase<TESTID>
{
public override TESTID Deserialize(MongoDB.Bson.Serialization.BsonDeserializationContext context, MongoDB.Bson.Serialization.BsonDeserializationArgs args)
{
return new TESTID(context.Reader.ReadString());
}

public override void Serialize(MongoDB.Bson.Serialization.BsonSerializationContext context, MongoDB.Bson.Serialization.BsonSerializationArgs args, TESTID value)
{
if (value.Value is null)
{
context.Writer.WriteNull();
}
else
{
context.Writer.WriteString(value.Value);
}
}
}
24 changes: 24 additions & 0 deletions src/StronglyTypedIds/Templates/ObjectId/ObjectId_Base.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
 readonly partial struct TESTID : INTERFACES
{
public MongoDB.Bson.ObjectId Value { get; }

public TESTID(MongoDB.Bson.ObjectId value)
{
Value = value;
}

public static TESTID New() => new TESTID(MongoDB.Bson.ObjectId.GenerateNewId());
public static readonly TESTID Empty = new TESTID(MongoDB.Bson.ObjectId.Empty);

public bool Equals(TESTID other) => this.Value.Equals(other.Value);
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
return obj is TESTID other && Equals(other);
}

public override int GetHashCode() => Value.GetHashCode();

public override string ToString() => Value.ToString();
public static bool operator ==(TESTID a, TESTID b) => a.Equals(b);
public static bool operator !=(TESTID a, TESTID b) => !(a == b);
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

public class DapperTypeHandler : Dapper.SqlMapper.TypeHandler<TESTID>
{
public override void SetValue(System.Data.IDbDataParameter parameter, TESTID value)
{
parameter.Value = value.Value == MongoDB.Bson.ObjectId.Empty ? null : value.Value.ToString();
}

public override TESTID Parse(object value)
{
return value switch
{
string stringValue when !string.IsNullOrEmpty(stringValue) => new TESTID(new MongoDB.Bson.ObjectId(stringValue)),
_ => throw new System.InvalidCastException($"Unable to cast object of type {value.GetType()} to TESTID"),
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

public class EfCoreValueConverter : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<TESTID, string>
{
public EfCoreValueConverter() : this(null) { }
public EfCoreValueConverter(Microsoft.EntityFrameworkCore.Storage.ValueConversion.ConverterMappingHints mappingHints = null)
: base(
id => id.Value.ToString(),
value => new TESTID(new MongoDB.Bson.ObjectId(value)),
mappingHints
) { }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
 public int CompareTo(TESTID other) => Value.CompareTo(other.Value);
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
 class TESTIDMongoSerializer : MongoDB.Bson.Serialization.Serializers.SerializerBase<TESTID>
{
public override TESTID Deserialize(MongoDB.Bson.Serialization.BsonDeserializationContext context, MongoDB.Bson.Serialization.BsonDeserializationArgs args)
{
return new TESTID(context.Reader.ReadObjectId());
}

public override void Serialize(MongoDB.Bson.Serialization.BsonSerializationContext context, MongoDB.Bson.Serialization.BsonSerializationArgs args, TESTID value)
{
context.Writer.WriteObjectId(value.Value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

class TESTIDNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter
{
public override bool CanConvert(System.Type objectType)
{
return objectType == typeof(TESTID);
}

public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
{
var id = (TESTID)value;
serializer.Serialize(writer, id.Value.ToString());
}

public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
{
var result = serializer.Deserialize<string>(reader);
return new TESTID(new MongoDB.Bson.ObjectId(result));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

class TESTIDSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter<TESTID>
{
public override TESTID Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
{
return new TESTID(new MongoDB.Bson.ObjectId(reader.GetString()));
}

public override void Write(System.Text.Json.Utf8JsonWriter writer, TESTID value, System.Text.Json.JsonSerializerOptions options)
{
if (value.Value == MongoDB.Bson.ObjectId.Empty)
{
writer.WriteNullValue();
}
else
{
writer.WriteStringValue(value.Value.ToString());
}
}
}
42 changes: 42 additions & 0 deletions src/StronglyTypedIds/Templates/ObjectId/ObjectId_TypeConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

class TESTIDTypeConverter : System.ComponentModel.TypeConverter
{
public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType)
{
return sourceType == typeof(MongoDB.Bson.ObjectId) || sourceType == typeof(string) || base.CanConvertFrom
(context, sourceType);
}

public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
return value switch
{
MongoDB.Bson.ObjectId objectIdValue => new TESTID(objectIdValue),
string stringValue when !string.IsNullOrEmpty(stringValue) => new TESTID(new MongoDB.Bson.ObjectId(stringValue)),
_ => base.ConvertFrom(context, culture, value),
};
}

public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType)
{
return sourceType == typeof(MongoDB.Bson.ObjectId) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType);
}

public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType)
{
if (value is TESTID idValue)
{
if (destinationType == typeof(MongoDB.Bson.ObjectId))
{
return idValue.Value;
}

if (destinationType == typeof(string))
{
return idValue.Value.ToString();
}
}

return base.ConvertTo(context, culture, value, destinationType);
}
}
Loading