簡體   English   中英

MongoDB C#驅動程序-序列化集合到接口

[英]MongoDB C# driver - Serialize collection to interface

由於工作環境的限制,我在MongoDB中實現了一個粗糙的Event Sourcing存儲。 我試圖像這樣從Mongo獲取IClientEvents的列表:

 var events = await _db.GetCollection<IClientEvent>("ClientEvents").FindAsync(c => c.ClientId == clientId);

運行上述存儲庫方法時,出現以下異常:

Message: System.InvalidOperationException : {document}.ClientId is not supported.

IClientEvent接口定義為:

public interface IClientEvent
{
    Guid Id { get; set; }
    long TimeStamp { get; set; }
    Guid ClientId { get; set; }
}

public class ClientChangedEvent : IClientEvent
{
    public Guid Id { get; set; }
    public long TimeStamp { get; set; }
    public Guid ClientId { get; set; }

    public IEnumerable<Change> Changes;
    // ... other properties for the event
}

單個集合中將存儲許多不同的事件類型,所有這些類型都將實現IClientEvent 我只想在一個調用中通過clientId獲得Client發生的所有事件。

我已經注冊了IClientEvent所有具體實現,甚至添加了自定義標識符:

        var clientEventsDiscriminator = new ClientEventsMongoDiscriminatorConvention();
        BsonSerializer.RegisterDiscriminatorConvention(typeof(IClientEvent),clientEventsDiscriminator);
        BsonClassMap.RegisterClassMap<ClientChangedEvent>();
        BsonSerializer.RegisterDiscriminatorConvention(typeof(ClientChangedEvent), clientEventsDiscriminator);

我什至嘗試按照本SO文章中的說明注冊ImpliedImplementationInterfaceSerializer ,但是當我注冊第二個具體實現時已經拋出異常,因為我已經為IClientEvent注冊了序列化IClientEvent

不知道從這里去哪里。 任何幫助是極大的贊賞!

-編輯更多代碼:

這是完整的注冊碼:

        var clientEventsDiscriminator = new ClientEventsMongoDiscriminatorConvention();
        BsonSerializer.RegisterDiscriminatorConvention(typeof(IClientEvent),clientEventsDiscriminator);

        clientEventsDiscriminator.AddEventType<ClientChangedEvent>();
        BsonClassMap.RegisterClassMap<ClientChangedEvent>();
        BsonSerializer.RegisterDiscriminatorConvention(typeof(ClientChangedEvent), clientEventsDiscriminator);

        clientEventsDiscriminator.AddEventType<ClientAddedEvent>();
        BsonClassMap.RegisterClassMap<ClientAddedEvent>();
        BsonSerializer.RegisterDiscriminatorConvention(typeof(ClientAddedEvent), clientEventsDiscriminator);

這是鑒別符:

    public class ClientEventsMongoDiscriminatorConvention : IDiscriminatorConvention
{
    private Dictionary<string, Type> _eventTypes = new Dictionary<string, Type>();

    public string ElementName => "_eventType";

    public BsonValue GetDiscriminator(Type nominalType, Type actualType)
    {
        return GetDiscriminatorValueForEventType(actualType);
    }

    public Type GetActualType(IBsonReader bsonReader, Type nominalType)
    {
        var bookmark = bsonReader.GetBookmark();
        bsonReader.ReadStartDocument();
        if (!bsonReader.FindElement(ElementName))
        {
            throw new InvalidCastException($"Unable to find property '{ElementName}' in document. Cannot map to an EventType.");
        }

        var value = bsonReader.ReadString();
        bsonReader.ReturnToBookmark(bookmark);

        if (_eventTypes.TryGetValue(value, out var type))
        {
            return type;
        }

        throw new InvalidCastException($"The type '{value}' has not been registered with the '{nameof(ClientEventsMongoDiscriminatorConvention)}'.");
    }

    private string GetDiscriminatorValueForEventType(Type type)
    {
        var indexOfEventWord = type.Name.IndexOf("Event");
        if (indexOfEventWord == -1)
        {
            return type.Name;
        }
        return type.Name.Substring(0, indexOfEventWord);
    }

    public void AddEventType<T>()
    {
        var discriminatorName = GetDiscriminatorValueForEventType(typeof(T));
        _eventTypes.TryAdd(discriminatorName, typeof(T));
    }
}

運行代碼時,似乎從未命中鑒別器的GetActualType方法。

通過將IClientEvent從接口更改為抽象類,我設法使其正常工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM