我将Marten用作事件存储,尤其是要获取事件流。
stream
IReadOnlyList<IEvent>
被IEvent
和public interface IEvent
{
Guid Id { get; set; }
int Version { get; set; }
long Sequence { get; set; }
object Data { get; }
Guid StreamId { get; set; }
string StreamKey { get; set; }
DateTimeOffset Timestamp { get; set; }
string TenantId { get; set; }
void Apply<TAggregate>(TAggregate state, IAggregator<TAggregate> aggregator) where TAggregate : class, new();
}
定义为:
IEvent
如果AccountEvents
属性的基础类型是Data
(如果不是,则不会将每个AccountEvents
转换为as
,顺序)。
在C#中,我将仅使用关键字let seqCastOption<'T> sequence =
sequence
|> Seq.map(fun x ->
match box x with
| :? 'T as value -> Some value
| _ -> None)
let fetchStream<'T> (session: IDocumentSession) (id: Guid) =
let stream = session.Events.FetchStream(id)
stream
|> Seq.map(fun x -> x.Data)
|> seqCastOption<'T>
|> Seq.filter (fun x -> x.IsSome)
|> Seq.map(fun x -> x.Value)
来实现这一目标,但是在F#中,我不确定(就性能而言)最快的F#ish方式是什么。
我结束了以下代码:
.Data
但这似乎很“昂贵”,我想知道将Option<AccountEvents>
转换为IsSome
+的步骤是否可以同时过滤{{1}}的步骤。 / p>
答案 0 :(得分:6)
rmunn答案中提到的public ObservableCollection<MyItem> MyList { get; }
= new ObservableCollection<MyItem>();
函数对于这种情况的了解非常有用,但是对于这种情况,我建议使用内置的.NET方法Seq.choose
,该方法确实可以完成您想要并且可能已经非常优化:
Enumerable.OfType<'T>
答案 1 :(得分:3)
Seq.choose
是您一直在寻找的功能。您为它提供了一个函数,该函数采用'A
并返回'B option
,并产生'B
的值Some
。对于您的使用情况,它看起来像这样:
let castOption<'T> x =
match box x with
| :? 'T as value -> Some value
| _ -> None
let fetchStream<'T> (session: IDocumentSession) (id: Guid) =
let stream = session.Events.FetchStream(id)
stream
|> Seq.map(fun x -> x.Data)
|> Seq.choose castOption<'T>