/// <summary> /// Reads instant data from the stream at the given cursor time and pushes it to all registered adapting data providers. /// </summary> /// <param name="reader">The simple reader that will read the data.</param> /// <param name="cursorTime">The cursor time at which to read the data.</param> /// <param name="indexCache">The stream reader's index cache.</param> public void ReadInstantData(ISimpleReader reader, DateTime cursorTime, ObservableKeyedCache <DateTime, IndexEntry> indexCache) { // Get the index of the data, given the cursor time int index = IndexHelper.GetIndexForTime(cursorTime, indexCache?.Count ?? 0, (idx) => indexCache[idx].OriginatingTime, this.CursorEpsilon); T data = default; IndexEntry indexEntry = default; if (index >= 0) { // Get the index entry indexEntry = indexCache[index]; // Read the data data = reader.Read <T>(indexEntry); } // Notify each adapting data provider of the new data foreach (IAdaptingInstantDataProvider <T> adaptingInstantDataProvider in this.dataProviders.ToList()) { adaptingInstantDataProvider.PushData(data, indexEntry); } // Release the reference to the local copy of the data if it's shared if (this.isSharedType && data != null) { (data as IDisposable).Dispose(); } }
/// <summary> /// Reads instant data from the stream at the given cursor time and pushes it to all registered adapting data providers. /// </summary> /// <param name="reader">The simple reader that will read the data.</param> /// <param name="cursorTime">The cursor time at which to read the data.</param> /// <param name="indexCache">The stream reader's index cache.</param> public void ReadInstantData(ISimpleReader reader, DateTime cursorTime, ObservableKeyedCache <DateTime, IndexEntry> indexCache) { // Get the index of the data, given the cursor time int index = IndexHelper.GetIndexForTime(cursorTime, indexCache?.Count ?? 0, (idx) => indexCache[idx].OriginatingTime, this.CursorEpsilon); T data = default; IndexEntry indexEntry = default; if (index >= 0) { // Get the index entry indexEntry = indexCache[index]; // Read the data data = reader.Read <T>(indexEntry); } // Notify all registered adapting data providers of the new data. If the data is Shared<T> then perform a deep clone // (which resolves to an AddRef() for this type) for each provider we call. The providers are responsible for releasing // their reference to the data once they're done with it. if (this.isSharedType && data != null) { Parallel.ForEach(this.dataProviders.ToList(), provider => provider.PushData(data.DeepClone <T>(), indexEntry)); // Release the reference to the local copy of the data (data as IDisposable).Dispose(); } else { Parallel.ForEach(this.dataProviders.ToList(), provider => provider.PushData(data, indexEntry)); } }
/// <inheritdoc /> public TDest Read <TDest>(ISimpleReader reader, IndexEntry indexEntry) { if (this.StreamBinding.StreamAdapter == null) { return(reader.Read <TDest>(indexEntry)); } else { var genericRead = typeof(ISimpleReader) .GetMethod("Read", new Type[] { typeof(IndexEntry) }) .MakeGenericMethod(this.StreamBinding.StreamAdapter.SourceType); var src = genericRead.Invoke(reader, new object[] { indexEntry }); var adaptData = typeof(StreamAdapter <,>) .MakeGenericType(this.StreamBinding.StreamAdapter.SourceType, this.StreamBinding.StreamAdapter.DestinationType) .GetMethod("AdaptData"); return((TDest)adaptData.Invoke(this.StreamBinding.StreamAdapter, new object[] { src })); } }