Source/Tx.Windows/EtwTdh/EtwTdhEvent.cs (125 lines of code) (raw):
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections;
using System.Collections.Generic;
namespace Tx.Windows
{
/// <summary>
/// This class implements lazy deserialization:
/// - It keeps a pointer to the ETW native structure
/// - If the caller accesses system fields like EventId, it returns them without copying
/// - If the caller asks for something more complex, such as Message the entire event is copied
/// </summary>
class EtwTdhEvent : IDictionary<string, object>
{
EtwTdhDeserializer _deserializer;
EtwNativeEvent _nativeEvent;
IDictionary<string, object> _materializedEvent;
public EtwTdhEvent(EtwTdhDeserializer deserializer, EtwNativeEvent nativeEvent)
{
_deserializer = deserializer;
_nativeEvent = nativeEvent;
}
/// <summary>
/// Method that materializes the event br reading (deserializing) the ETW data
/// Calling this second time is ignored as the event is already materialized
/// </summary>
void Materialize()
{
if (_materializedEvent != null)
{
return; // the event is already materialized
}
_materializedEvent = _deserializer.Deserialize(ref _nativeEvent);
}
static Dictionary<string, Func<EtwNativeEvent, object>> _systemFields = new Dictionary<string, Func<EtwNativeEvent, object>>
{
{ "EventId", e=>e.Id },
{ "ProviderId", e=>e.ProviderId },
{ "Version", e=>e.Version },
{ "TimeCreated", e=>e.TimeStamp.UtcDateTime },
{ "ProcessId", e=>e.ProcessId },
{ "ThreadId", e=>e.ThreadId },
{ "ActivityId", e=>e.ActivityId }
};
public object this[string key]
{
get
{
Func<EtwNativeEvent, object> accessor = null;
if (_systemFields.TryGetValue(key, out accessor))
{
return accessor(_nativeEvent);
}
Materialize();
return _materializedEvent[key];
}
set => throw new NotSupportedException();
}
public ICollection<string> Keys
{
get
{
Materialize();
return _materializedEvent.Keys;
}
}
public ICollection<object> Values
{
get
{
if (_materializedEvent == null)
{
Materialize();
}
return _materializedEvent.Values;
}
}
public int Count => throw new NotImplementedException();
public bool IsReadOnly => throw new NotImplementedException();
public void Add(string key, object value)
{
throw new NotImplementedException();
}
public void Add(KeyValuePair<string, object> item)
{
throw new NotImplementedException();
}
public void Clear()
{
throw new NotImplementedException();
}
public bool Contains(KeyValuePair<string, object> item)
{
throw new NotImplementedException();
}
public bool ContainsKey(string key)
{
if (_materializedEvent == null)
{
return _systemFields.ContainsKey(key);
}
return _materializedEvent.ContainsKey(key);
}
public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
{
throw new NotImplementedException();
}
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
{
return _materializedEvent.GetEnumerator();
}
public bool Remove(string key)
{
throw new NotImplementedException();
}
public bool Remove(KeyValuePair<string, object> item)
{
throw new NotImplementedException();
}
public bool TryGetValue(string key, out object value)
{
if (_systemFields.TryGetValue(key, out Func<EtwNativeEvent, object> accessor))
{
value = accessor(_nativeEvent);
return true;
}
Materialize();
return _materializedEvent.TryGetValue(key, out value);
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
}