Skip to content

Instantly share code, notes, and snippets.

@JamisonWhite
Last active February 6, 2023 13:07
Show Gist options
  • Save JamisonWhite/cc0eae9e0ebfe8e62ec3 to your computer and use it in GitHub Desktop.
Save JamisonWhite/cc0eae9e0ebfe8e62ec3 to your computer and use it in GitHub Desktop.
C# MongoDb custom field and value discriminator
/// <summary>
/// Map a resource "keyType" to polymorphic classes.
/// </summary>
/// <remarks>
/// Followed example here:
/// http://pastebin.com/9UweEKBe
/// </remarks>
public class CustomFieldDiscriminatorConvention : IDiscriminatorConvention
{
private readonly string elementName;
private readonly Type defaultType;
private readonly Dictionary<string, Type> typeMap;
public CustomFieldDiscriminatorConvention(string elementName, Type defaultType, Dictionary<string, Type> typeMap)
{
this.elementName = elementName;
this.defaultType = defaultType;
this.typeMap = typeMap;
}
/// <summary>
/// Element Name
/// </summary>
public string ElementName
{
get { return elementName; }
}
/// <summary>
/// Return the type that matches the string
/// </summary>
/// <param name="bsonReader"></param>
/// <param name="nominalType"></param>
/// <returns></returns>
public Type GetActualType(MongoDB.Bson.IO.BsonReader bsonReader, Type nominalType)
{
Type type = defaultType;
var bookmark = bsonReader.GetBookmark();
bsonReader.ReadStartDocument();
if (bsonReader.FindElement(ElementName))
{
var value = bsonReader.ReadString();
if (typeMap.ContainsKey(value.ToLower()))
type = typeMap[value];
}
bsonReader.ReturnToBookmark(bookmark);
return type;
}
public BsonValue GetDiscriminator(Type nominalType, Type actualType)
{
return actualType.Name;
}
}
var dis = new CustomFieldDiscriminatorConvention(
"keyType",
typeof(Resource),
new Dictionary<string, Type>(3)
{
{"domain", typeof (DomainResource)},
{"ip", typeof (IpResource)},
{"uri", typeof (UriResource)}
}
);
BsonSerializer.RegisterDiscriminatorConvention(typeof(Resource), dis);
@benprime
Copy link

@razzeee That makes sense, but I couldn't find a way to provide a default value for documents saved to the database before the discriminators were implemented using ScalarDiscriminatorConvention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment