Neventstore 保持事件类名称的事件上转换

Neventstore 保持事件类名称的事件上转换,neventstore,Neventstore,NEventStore 3.2.0.0 据我所知,NEventStore要求旧事件类型必须保留在左右,以便进行事件上转换。 要使它们在将来正确反序列化,它们必须具有唯一的名称。建议将其命名为event\u VERSION 有没有办法避免EventV1,EventV2,…,EventVN,弄乱您的域模型,并且只需继续使用Event? 你的策略是什么?在很久很久以前的一个问题中,一个答案不见了 在评论中提到的讨论中,我提出了一个——我可以说——优雅的解决方案: 不保存类型名称,而是保存(版本控制的)

NEventStore 3.2.0.0

据我所知,NEventStore要求旧事件类型必须保留在左右,以便进行事件上转换。
要使它们在将来正确反序列化,它们必须具有唯一的名称。建议将其命名为
event\u VERSION

有没有办法避免
EventV1
EventV2
,…,
EventVN
弄乱您的域模型,并且只需继续使用
Event

你的策略是什么?

在很久很久以前的一个问题中,一个答案不见了

在评论中提到的讨论中,我提出了一个——我可以说——优雅的解决方案:

不保存类型名称,而是保存(版本控制的)标识符

标识符由类级别的属性设置,即

名称空间CurrentEvents
{
[版本控制(“EventSomethingOccessed”,0)]//仍然是版本0
公开课事件发生了什么事
{
...
}
}
此标识符应在有效负载中/旁边序列化。以序列化形式
“Some.Name.Space.EventSomeThingOccessed”->“EventSomeThingOccessed | 0”

当需要此事件的另一个版本时,当前版本将复制到“遗留”程序集中或另一个命名空间中,并重命名(类型名称)为“EventSomethingHappenedV0”-但
版本化的
-属性保持不变(在此副本中)

名称空间事件
{
[版本控制(“EventSomethingOccessed”,0)]//仍然是版本0
公共类事件发生了一些事情Dv0
{
...
}
}
在新版本中(在相同的位置,在相同的名称下),只增加属性的版本部分。就这样

名称空间CurrentEvents
{
[版本控制(“EventSomethingOccessed”,1)]//新版本1
公开课事件发生了什么事
{
...
}
}
Json.NET支持将类型标识符映射到类型并返回的绑定器。这是一个生产用活页夹:

公共类VersionedSerializationBinder:DefaultSerializationBinder
{
私有字典_getImplementationLookup=新字典();
私有静态类型[]_versionedEvents=null;
受保护的静态类型[]VersionedEvents
{
得到
{
如果(_versiondevents==null)
_versionedEvents=AppDomain.CurrentDomain.GetAssemblys()
.其中(x=>x.IsDynamic==false)
.SelectMany(x=>x.GetExportedTypes()
.其中(y=>y.IsAbstract==false&&
y、 IsInterface==false)
.Where(x=>x.GetCustomAttributes(typeof(VersionedAttribute),false).Any())
.ToArray();
返回_versiondevents;
}
}
公共版本SerializationBinder()
{
}
私有版本数据属性GetVersionInformation(类型)
{
var attr=type.GetCustomAttributes(typeof(VersionedAttribute),false).Cast().FirstOrDefault();
返回属性;
}
公共重写void BindToName(类型serializedType、输出字符串assemblyName、输出字符串typeName)
{
var versionInfo=GetVersionInformation(serializedType);
if(versionInfo!=null)
{
var impl=GetImplementation(versionInfo);
typeName=versionInfo.Identifier+“|”+versionInfo.Revision;
}
其他的
{
base.BindToName(serializedType、out assemblyName、out typeName);
}
assemblyName=null;
}
私有版本数据属性GetVersionInformation(字符串序列化信息)
{
var strs=serializedInfo.Split(新[]{'|'},StringSplitOptions.RemoveEmptyEntries);
如果(标准长度!=2)
返回null;
返回新的VersionedAttribute(strs[0],strs[1]);
}
公共重写类型BindToType(字符串assemblyName、字符串typeName)
{
if(typeName.Contains(“|”))
{
var type=GetImplementation(GetVersionInformation(typeName));
if(type==null)
抛出新的InvalidOperationException(string.Format(“VersionDeventSerializationBinder:找不到类型标识符“{0}”的实现,typeName));
返回类型;
}
其他的
{
var versionInfo=GetVersionInformation(typeName+“|0”);
if(versionInfo!=null)
{
var type=GetImplementation(versionInfo);
if(type!=null)
返回类型;
//else:继续,因为它是正常的序列化对象。。。
}
}
//解析程序集名称(如果不在序列化信息中)
if(string.IsNullOrEmpty(assemblyName))
{
类型;
if(typeName.TryFindType(out类型))
{
assemblyName=type.Assembly.GetName().Name;
}
}
返回base.BindToType(assemblyName,typeName);
}
私有类型GetImplementation(VersionedAttribute属性)
{
类型eventType=null;
if(_getImplementationLookup.TryGetValue(attribute.Identifier+“|”+attribute.Revision,out eventType)==false)
{
var events=VersionedEvents
.其中(x=>
{
返回x.GetCustomAttributes(typeof(VersionedAttribute),false)
.Cast()
.其中(y=>
y、 修订==属性。修订&&
y、 标识符==属性。标识符)
.Any();
})
.ToArray();
如果(events.Length==0)
{
eventType=null;
}
else if(events.Length==1)
{
eventType=事件[0]