【问题标题】:BsonClassMap for Types Containing Generics包含泛型的类型的 BsonClassMap
【发布时间】:2013-11-08 21:50:48
【问题描述】:

我们正在使用 Bson 在 RabbitMq Rpc 客户端服务器调用的任一侧进行序列化/反序列化。我们已经按照这里的建议实现了我们的 SimpleRpcClient/Server:

https://www.rabbitmq.com/releases/rabbitmq-dotnet-client/v3.1.5/rabbitmq-dotnet-client-3.1.5-client-htmldoc/html/type-RabbitMQ.Client.MessagePatterns.SimpleRpcServer.html

但是,我们的 Subscription 对象是这样实现的:

public class SubscriberRequest<TKey> : SubscriberRequest
{
    public TKey[] Keys { get; set; }

    public SubscriberRequest(){}

    public SubscriberRequest(IEnumerable<TKey> keys) : base()
    {
        this.Keys = keys.ToArray();
        this.Hostname = Dns.GetHostName();
    }
}

public class SubscriberRequest
{
    public static SubscriberRequest Default = new SubscriberRequest() { Hostname = Dns.GetHostName() };

    public string Hostname { get; set; }
}

允许我们以类型化的方式来回发送请求响应对象。当我们的序列化程序只负责处理一种类型的“请求”对象时,这似乎工作得很好。

BsonClassMap.LookupClassMap(typeof(SubscriberRequest<MessageType1Request>));

但是,当我们尝试将序列化器用于多种类型的请求对象时,我似乎无法将 ClassMap 设置为足以满足反序列化器的要求。

BsonClassMap.LookupClassMap(typeof(SubscriberRequest<MessageType1Request>));
BsonClassMap.LookupClassMap(typeof(SubscriberRequest<MessageType2Request>));

我一直收到 MongoDB.Bson.BsonSerializationException: Ambiguous discriminator 'SubscriberRequest`1'

我试图明确告诉 BsonClassMap 如何处理这个问题:

        BsonClassMap.RegisterClassMap<SubscriberRequest<MessageType1Request>>(cm =>
            {
                cm.MapCreator(p => new SubscriberRequest<MessageType1Request>(p.Keys));
            }); 

无济于事。

如何正确满足判别器?

【问题讨论】:

  • 这个问题有什么解决办法吗?

标签: c# serialization rabbitmq mongodb-.net-driver bson


【解决方案1】:

我自己也遇到了。

解决方案是覆盖每个泛型类型的鉴别器,以便在序列化时它们获得唯一值。

对于你的情况,这样的事情应该可以工作:

BsonClassMap.RegisterClassMap<SubscriberRequest<MessageType1Request>>(cm =>
{
    cm.AutoMap();
    cm.SetDiscriminator("SubscriberRequest`MessageType1Request");
};
BsonClassMap.RegisterClassMap<SubscriberRequest<MessageType2Request>>(cm =>
{
    cm.AutoMap();
    cm.SetDiscriminator("SubscriberRequest`MessageType2Request");
};

【讨论】:

    【解决方案2】:

    我找到了这个并做了一个小的修改MongoDB C# driver type discriminators with generic class inheriting from non-generic base class

    按照@Bruce Nielsen 的建议设置鉴别器不是很灵活

    public class DiscriminatorConvention<T> : IDiscriminatorConvention
    {
        public string ElementName => "_t";
    
        public Type GetActualType(IBsonReader bsonReader, Type nominalType)
        {
            if (!typeof(T).IsAssignableFrom(nominalType))
                    throw new Exception($"Cannot use DiscriminatorConvention<{typeof(T).Name}> for type " + nominalType);
    
            var ret = nominalType;
    
            var bookmark = bsonReader.GetBookmark();
            bsonReader.ReadStartDocument();
            if (bsonReader.FindElement(ElementName))
            {
                var value = bsonReader.ReadString();
                ret = Type.GetType(value);
    
                if (ret == null)
                    throw new Exception("Could not find type from " + value);
    
                if (!typeof(T).IsAssignableFrom(ret) && !ret.IsSubclassOf(typeof(T)))
                    throw new Exception("type is not an IRestriction");
            }
    
            bsonReader.ReturnToBookmark(bookmark);
    
            return ret;
        }
    
        public BsonValue GetDiscriminator(Type nominalType, Type actualType)
        {
            if (nominalType != typeof(Setting))
                throw new Exception($"Cannot use {GetType().Name} for type " + nominalType);
    
            return actualType.AssemblyQualifiedName; // ok to use since assembly version is ignored when deserialized
        }
    }
    

    【讨论】:

      【解决方案3】:

      我认为你需要这样的东西:Serialize Documents with the C# Driver - Specifying Known Types

      基本上,您需要映射所有已知类型,以便鉴别器确定您想要什么。

      BsonClassMap.RegisterClassMap<SubscriberRequest<MessageType1Request>>();
      BsonClassMap.RegisterClassMap<SubscriberRequest<MessageType2Request>>();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-13
        • 2015-08-25
        • 1970-01-01
        • 1970-01-01
        • 2020-12-11
        • 1970-01-01
        • 1970-01-01
        • 2015-03-04
        相关资源
        最近更新 更多