Source/Tx.Windows.Logs/EvtxTypeMap.cs (92 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.Generic;
using System.Diagnostics.Eventing.Reader;
using System.Linq.Expressions;
using System.Reactive;
using System.Reflection;
namespace Tx.Windows
{
public class EvtxTypeMap : IRootTypeMap<EventRecord, SystemEvent>
{
private static readonly Dictionary<string, Type> _typeMap = new Dictionary<string, Type>
{
{"win:Int8", typeof (sbyte)},
{"win:UInt8", typeof (byte)},
{"win:Int16", typeof (short)},
{"win:UInt16", typeof (ushort)},
{"win:Int32", typeof (int)},
{"win:UInt32", typeof (uint)},
{"win:Int64", typeof (long)},
{"win:UInt64", typeof (ulong)},
{"win:Pointer", typeof (ulong)},
{"win:UnicodeString", typeof (string)},
{"win:AnsiString", typeof (string)}
};
public Func<EventRecord, DateTimeOffset> TimeFunction
{
get { return evt => evt.TimeCreated != null ? evt.TimeCreated.Value.ToUniversalTime() : new DateTimeOffset(); }
}
public Func<EventRecord, object> GetTransform(Type outputType)
{
Expression<Func<EventRecord, SystemEvent>> template = e => new SystemEvent
{
Header = new SystemHeader
{
ActivityId = e.ActivityId.HasValue ? e.ActivityId.Value : Guid.Empty,
Channel = 0,
Context = e.LogName,
Level = e.Level.Value,
EventId = (ushort) e.Id,
Keywords = e.Keywords.HasValue ? (ulong) e.Keywords.Value : (ulong) 0,
Opcode = e.Opcode.HasValue ? (byte) e.Opcode.Value : (byte) 0,
ProcessId = e.ProcessId.HasValue ? (uint) e.ProcessId.Value : 0,
ProviderId = e.ProviderId.HasValue ? e.ProviderId.Value : Guid.Empty,
RelatedActivityId = e.RelatedActivityId.HasValue ? e.RelatedActivityId.Value : Guid.Empty,
Task = e.Task.HasValue ? (ushort) e.Task.Value : (ushort) 0,
ThreadId = e.ThreadId.HasValue ? (uint) e.ThreadId.Value : (uint) 0,
Timestamp = e.TimeCreated.HasValue ? e.TimeCreated.Value : DateTime.MinValue,
Version = e.Version.HasValue ? e.Version.Value : (byte) 0
}
};
if (outputType == typeof (SystemEvent))
return template.Compile();
LambdaExpression ex = template;
var mi = (MemberInitExpression) ex.Body;
var bindings = new List<MemberBinding>(mi.Bindings);
ParameterExpression record = ex.Parameters[0];
PropertyInfo[] properties = outputType.GetProperties();
int index = 0;
foreach (PropertyInfo p in properties)
{
var attribute = p.GetCustomAttribute<EventFieldAttribute>();
if (attribute == null) continue;
// the following is to handle value maps, that were emitted as enumerations
Type t;
if (p.PropertyType.IsEnum)
t=p.PropertyType;
else
t = GetSimpleType(attribute.OriginalType);
MemberAssignment b = Expression.Bind(p, Expression.Convert(
Expression.Property(
Expression.Call(
Expression.Property(record,
typeof(EventRecord).GetProperty(
"Properties")),
typeof(IList<EventProperty>).GetMethod("get_Item"),
Expression.Constant(index++)),
typeof(EventProperty).GetProperty("Value")),
t));
bindings.Add(b);
}
NewExpression n = Expression.New(outputType);
MemberInitExpression m = Expression.MemberInit(n, bindings.ToArray());
UnaryExpression cast = Expression.Convert(m, typeof (object));
Expression<Func<EventRecord, object>> exp = Expression.Lambda<Func<EventRecord, object>>(cast, ex.Parameters);
return exp.Compile();
}
protected Type GetSimpleType(string winType)
{
return _typeMap[winType];
}
}
}