MongoDB C#驱动程序-将集合序列化到接口

MongoDB C#驱动程序-将集合序列化到接口,c#,mongodb,interface,mongodb-.net-driver,event-sourcing,C#,Mongodb,Interface,Mongodb .net Driver,Event Sourcing,由于工作环境的限制,我正在MongoDB中实现一个粗糙的事件源商店。我正试图从Mongo获取IClientEvents列表,如下所示: var events = await _db.GetCollection<IClientEvent>("ClientEvents").FindAsync(c => c.ClientId == clientId); IClientEvent接口定义为: public interface IClientEvent { Guid Id {

由于工作环境的限制,我正在MongoDB中实现一个粗糙的事件源商店。我正试图从Mongo获取
IClientEvents
列表,如下所示:

 var events = await _db.GetCollection<IClientEvent>("ClientEvents").FindAsync(c => c.ClientId == clientId);
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
}
我甚至尝试注册了中提到的
ImpliedImplementationInterfaceSerializer
,但当我注册第二个具体实现时,它抛出了一个异常,我已经为
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);
var clientventsdiscriminator=new clientventsmongodiscriminatorconvention();
b序列化器、注册器鉴别规则(类型为(IClientEvent)、客户鉴别规则);
clientEventsDiscriminator.AddEventType();
BsonClassMap.RegisterClassMap();
b序列化器、注册器歧视约定(类型(ClientChangedEvent)、clientventsdiscriminator);
clientEventsDiscriminator.AddEventType();
BsonClassMap.RegisterClassMap();
b序列化器、注册器鉴别规则(typeof(ClientAddedEvent)、clientEventsDiscriminator);
这是鉴别器:

        var clientEventsDiscriminator = new ClientEventsMongoDiscriminatorConvention();
        BsonSerializer.RegisterDiscriminatorConvention(typeof(IClientEvent),clientEventsDiscriminator);
        BsonClassMap.RegisterClassMap<ClientChangedEvent>();
        BsonSerializer.RegisterDiscriminatorConvention(typeof(ClientChangedEvent), 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));
    }
}
公共类客户投诉Mongodi投诉:IDiscriminator投诉
{
私有字典_eventTypes=新字典();
公共字符串ElementName=>“\u eventType”;
公共BsonValue GetDiscriminator(类型nominalType、类型actualType)
{
返回GetDiscriminatorValueForEventType(实际类型);
}
公共类型GetActualType(IBMsonReader bsonReader,类型nominalType)
{
var bookmark=bsonReader.GetBookmark();
bsonReader.ReadStartDocument();
if(!bsonReader.FindElement(ElementName))
{
抛出新的InvalidCastException($“无法在文档中找到属性“{ElementName}”。无法映射到EventType。”);
}
var value=bsonReader.ReadString();
b sonreader.ReturnToBookmark(书签);
if(_eventTypes.TryGetValue(value,out var type))
{
返回类型;
}
抛出新的InvalidCastException($“类型“{value}”尚未注册到“{nameof(ClientEventsMongoDiscriminatorConvention)}”中”;
}
私有字符串GetDiscriminatorValueForEventType(类型)
{
var indexOfEventWord=type.Name.IndexOf(“事件”);
if(indexOfEventWord==-1)
{
返回类型.名称;
}
返回类型.Name.Substring(0,indexOfEventWord);
}
public void AddEventType()
{
var discriminatorName=GetDiscriminatorValueForEventType(typeof(T));
_TryAdd(discriminatorName,typeof(T));
}
}

运行代码时,它似乎从来没有碰到鉴别器的
GetActualType
方法。

我通过简单地将
IClientEvent
从接口更改为抽象类,使其工作。

您确定不需要为该存储库方法提供具体类型吗?存储库方法如何知道
ClientChangedEvent
是您想要的实现?您的问题还不清楚
clientventsmongodiscriminatorconvention
是否提供了必要的映射。您还没有向我们展示该代码。请尝试将接口属性公开。嘿@RobertHarvey-我已使用您要求的代码编辑了该问题。如前所述-在运行代码时,鉴别器的
GetActualType
meothod看起来不会被击中。@jdweng-使用public/private/等装饰接口属性/方法是不合法的。这意味着它是公共的。
    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));
    }
}