我目前正在将[BsonRepresentation(BsonType.String)]
属性应用于我的域模型中的所有Guid
属性,以便以字符串格式序列化这些属性。除了令人厌倦之外,有时候这种情况并不常见,例如:使用自定义Wrapper<T>
类:
public class Wrapper<T>
{
public T Value { get; set; }
// Further properties / business logic ...
}
当T
为Guid
时,Value
属性将存储为UuidLegacy
类型的二进制数据(任何类型为Guid
的属性都不会存储用上面的属性装饰)。但是,我希望所有Guid
,包括Wrapper<Guid>.Value
,都表示为数据库中的字符串。
有没有办法告诉MongoDB C#驱动程序以字符串格式存储所有Guid
?
答案 0 :(得分:6)
这可以使用惯例
来实现有些事情:
var myConventions = new ConventionProfile();
myConventions.SetSerializationOptionsConvention(
new TypeRepresentationSerializationOptionsConvention(typeof (Guid), BsonType.String));
BsonClassMap.RegisterConventions(myConventions, t => t == typeof (MyClass));
这应该在您的应用启动中的某个位置。
答案 1 :(得分:4)
虽然使用约定会起作用,但要注意两个重要的(和相关的)要点:
filter
参数是必需的,如果过滤器过于笼统(例如:t => true
),则可能会覆盖其他已注册的约定。 另一种选择是为类型Guid创建一个BSON类映射,它将表示设置为字符串:
if (!BsonClassMap.IsClassMapRegistered(typeof(Guid))) {
BsonClassMap.RegisterClassMap<Guid>(cm => {
cm.AutoMap();
cm.Conventions.SetSerializationOptionsConvention(new TypeRepresentationSerializationOptionsConvention(typeof(Guid), BsonType.String));
});
}
这应该在使用BsonSerializer进行任何读/写之前完成,否则将创建默认的Class Map,并且您将无法更改Class Map。
答案 2 :(得分:3)
在没有设置Convention
的情况下全局执行此操作的替代方法(鉴于实际问题是有效的,我认为这是过度杀伤:“如何全局应用”)可以通过只需调用一行代码:
BsonSerializer.RegisterSerializer(typeof(Guid),
new GuidSerializer(BsonType.String));
请确保这是MongoDb序列化配置中的第一件事(即使在注册类映射之前,基于约定的解决方案也是如此)。
就我个人而言,我认为这是一个更好的解决方案,而不是创建一个带有'always return true'谓词的约定,大多数似乎都在暗示。约定适用于更复杂的场景,以及对谓词实际使用的序列化配置集进行分组,并且多个Conventions
捆绑到ConventionPack
中。但是,对于简单地应用全局序列化格式,只需使用上面的代码行保持简单。
如果您以后确定您的合法Convention
需要更改此规则,请注册它以覆盖我们设置的全局规则,就像您的Convention
会覆盖< em>默认全局规则,设置为Guid's
表示为BsonType.Binary
。最后的结果是全局规则优先,其次是Convention
,在适用自定义ConventionPack
的情况下,它将覆盖我们的自定义全局规则 (基于您的自定义谓词。)
答案 3 :(得分:0)
不推荐使用ConventionProfile。如果您不想全局应用规则,但仅针对特定类(这应该在您的应用启动中的某个位置):
var pack = new ConventionPack { new GuidAsStringRepresentationConvention () };
ConventionRegistry.Register("GuidAsString", pack, t => t == typeof (MyClass));
public class GuidAsStringRepresentationConvention : ConventionBase, IMemberMapConvention
{
public void Apply(BsonMemberMap memberMap)
{
if (memberMap.MemberType == typeof(Guid))
{
var serializer = memberMap.GetSerializer();
var representationConfigurableSerializer = serializer as IRepresentationConfigurable;
if (representationConfigurableSerializer != null)
{
var reconfiguredSerializer = representationConfigurableSerializer.WithRepresentation(BsonType.String);
memberMap.SetSerializer(reconfiguredSerializer);
}
}
}
}