Merge the .Net Native and CoreCLR implementations of EventSource. This replaces a...
authorDavid Mason <davmason@microsoft.com>
Mon, 21 Dec 2015 23:43:42 +0000 (15:43 -0800)
committerDavid Mason <davmason@microsoft.com>
Thu, 7 Jan 2016 22:58:21 +0000 (14:58 -0800)
Remove some ifdefs that can be done in a better way and merge additional bug fixes that happened in the nuget package branch.

Refactor some code to eliminate ifdefs for projectN.

Refactor code so that the ProjectN support uses partial classes instead of ifdefs.

Round 2 of making sure everything compiles in CoreCLR and in ProjectN.

Add formatting to the debugger message that EventSource prints when an internal error happens.

Change null strings to be represented as empty strings in TraceLogging.

Remove some ifdefs that can be done in a better way and merge additional bug fixes that happened in the nuget package branch.

Change WriteEventString to use an anonymous struct instead of EventMessage.

33 files changed:
src/mscorlib/model.xml
src/mscorlib/mscorlib.shared.sources.props
src/mscorlib/src/System/Diagnostics/Eventing/ActivityTracker.cs
src/mscorlib/src/System/Diagnostics/Eventing/EventCounter.cs [new file with mode: 0644]
src/mscorlib/src/System/Diagnostics/Eventing/EventDescriptor.cs
src/mscorlib/src/System/Diagnostics/Eventing/EventProvider.cs
src/mscorlib/src/System/Diagnostics/Eventing/EventSource.cs
src/mscorlib/src/System/Diagnostics/Eventing/EventSourceException.cs
src/mscorlib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs [new file with mode: 0644]
src/mscorlib/src/System/Diagnostics/Eventing/StubEnvironment.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/ArrayTypeInfo.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/DataCollector.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EnumHelper.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EnumerableTypeInfo.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventFieldFormat.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventSourceActivity.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/FieldMetadata.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/InvokeTypeInfo.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/NameInfo.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyAccessor.cs [deleted file]
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyAnalysis.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyValue.cs [new file with mode: 0644]
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/SimpleEventTypes.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/SimpleTypeInfos.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/Statics.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingDataCollector.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventSource.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventTypes.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingMetadataCollector.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingTypeInfo.cs
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingTypeInfo_T.cs [deleted file]
src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TypeAnalysis.cs
src/mscorlib/src/System/Diagnostics/Eventing/Winmeta.cs

index ecaa8f4..659d5be 100644 (file)
     </Type>
     <Type Status="ImplRoot" Name="System.Diagnostics.StackFrameHelper" />
 
-    <Type Status="ImplRoot" Name="System.Diagnostics.Tracing.EnumHelper&lt;UnderlyingType&gt;">
-      <Member Name="Identity(UnderlyingType)" />
-    </Type>
-
     <Type Name="System.Diagnostics.Tracing.EventAttribute">
       <Member Name="#ctor(System.Int32)" />
       <Member Name="get_EventId" />
index 33189a1..e14bdd6 100644 (file)
     <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventDescriptor.cs" />
     <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventProvider.cs" />
     <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventSource.cs" />
+    <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventSource_CoreCLR.cs" />
     <DiagnosticsSources Condition="'$(FeatureXplatEventSource)' == 'true'" Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\XplatEventLogger.cs" />
     <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventSourceException.cs" />
     <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\FrameworkEventSource.cs" />
     <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\FieldMetadata.cs" />
     <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\InvokeTypeInfo.cs" />
     <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\NameInfo.cs" />
-    <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\PropertyAccessor.cs" />
+    <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\PropertyValue.cs" />
     <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\PropertyAnalysis.cs" />
     <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\SimpleEventTypes.cs" />
     <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\SimpleTypeInfos.cs" />
     <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TraceLoggingEventTypes.cs" />
     <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TraceLoggingMetadataCollector.cs" />
     <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TraceLoggingTypeInfo.cs" />
-    <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TraceLoggingTypeInfo_T.cs" />
     <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TypeAnalysis.cs" />
   </ItemGroup>
   <ItemGroup>
index 54f7b47..dcd3f70 100644 (file)
@@ -12,7 +12,7 @@ using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
 
 #if ES_BUILD_STANDALONE
 namespace Microsoft.Diagnostics.Tracing
-#else    
+#else
 using System.Threading.Tasks;
 namespace System.Diagnostics.Tracing
 #endif
@@ -47,7 +47,7 @@ namespace System.Diagnostics.Tracing
         /// Called on work item begins.  The activity name = providerName + activityName without 'Start' suffix.
         /// It updates CurrentActivityId to track.   
         /// 
-        /// It returns true if the Start should be logged, otherwise (if it is illegal recurision) it return false. 
+        /// It returns true if the Start should be logged, otherwise (if it is illegal recursion) it return false. 
         /// 
         /// The start event should use as its activity ID the CurrentActivityId AFTER calling this routine and its
         /// RelatedActivityID the CurrentActivityId BEFORE calling this routine (the creator).  
@@ -64,12 +64,10 @@ namespace System.Diagnostics.Tracing
                 if (m_checkedForEnable)
                     return;
                 m_checkedForEnable = true;
-#if ES_BUILD_STANDALONE
-                Enable();           // Enable it unconditionally.  
-#else
-                if (System.Threading.Tasks.TplEtwProvider.Log.IsEnabled(EventLevel.Informational, System.Threading.Tasks.TplEtwProvider.Keywords.TasksFlowActivityIds))
-                     Enable();
-#endif
+                if (TplEtwProvider.Log.IsEnabled(EventLevel.Informational, TplEtwProvider.Keywords.TasksFlowActivityIds))
+                    Enable();
+                if (m_current == null)
+                    return;
             }
 
 
@@ -124,7 +122,7 @@ namespace System.Diagnostics.Tracing
 
             // Remember the current ID so we can log it 
             activityId = newActivity.ActivityId;
-
+            
             if (etwLog.Debug)
             {
                 etwLog.DebugFacilityMessage("OnStartRetActivityState", ActivityInfo.LiveActivities(newActivity));
@@ -144,7 +142,7 @@ namespace System.Diagnostics.Tracing
                 return;
 
             var fullActivityName = NormalizeActivityName(providerName, activityName, task);
-
+            
             var etwLog = TplEtwProvider.Log;
             if (etwLog.Debug)
             {
@@ -215,7 +213,7 @@ namespace System.Diagnostics.Tracing
                     }
                     return;
                 }
-                // We failed to stop it.  We must have hit a race condition to stop it.  Just start over and try again.  
+                // We failed to stop it.  We must have hit a race to stop it.  Just start over and try again.  
             }
         }
 
@@ -227,7 +225,17 @@ namespace System.Diagnostics.Tracing
         {
             if (m_current == null)
             {
-                m_current = new AsyncLocal<ActivityInfo>(ActivityChanging);
+                // Catch the not Implemented 
+                try
+                {
+                    m_current = new AsyncLocal<ActivityInfo>(ActivityChanging);
+                }
+                catch (NotImplementedException) {
+#if (!ES_BUILD_PCL && ! PROJECTN)
+                    // send message to debugger without delay
+                    System.Diagnostics.Debugger.Log(0, null, "Activity Enabled() called but AsyncLocals Not Supported (pre V4.6).  Ignoring Enable");
+#endif
+                } 
             }
         }
 
@@ -375,10 +383,10 @@ namespace System.Diagnostics.Tracing
                     {
                         // TODO FIXME - differentiate between AD inside PCL
                         int appDomainID = 0;
-#if !ES_BUILD_STANDALONE
+#if (!ES_BUILD_STANDALONE && !PROJECTN)
                         appDomainID = System.Threading.Thread.GetDomainID();
 #endif
-                        // We start with the appdomain number to make this unique among appdomains.                      
+                        // We start with the appdomain number to make this unique among appdomains.
                         activityPathGuidOffsetStart = AddIdToGuid(outPtr, activityPathGuidOffsetStart, (uint)appDomainID);
                     }
 
@@ -608,7 +616,7 @@ namespace System.Diagnostics.Tracing
         #endregion
     }
 
-#if ES_BUILD_STANDALONE
+#if ES_BUILD_STANDALONE || PROJECTN
     /******************************** SUPPORT *****************************/
     /// <summary>
     /// This is supplied by the framework.   It is has the semantics that the value is copied to any new Tasks that is created
@@ -617,12 +625,17 @@ namespace System.Diagnostics.Tracing
     /// only get your thread local copy which means that you never have races.  
     /// </summary>
     /// 
-    [EventSource(Name="Microsoft.Tasks.Nuget")]
+#if ES_BUILD_STANDALONE
+    [EventSource(Name = "Microsoft.Tasks.Nuget")]
+#else
+    [EventSource(Name = "System.Diagnostics.Tracing.TplEtwProvider")]
+#endif
     internal class TplEtwProvider : EventSource
     {
         public class Keywords
         {
-            public const EventKeywords Debug = (EventKeywords) 1;
+            public const EventKeywords TasksFlowActivityIds = (EventKeywords)0x80;
+            public const EventKeywords Debug = (EventKeywords)0x20000;
         }
 
         public static TplEtwProvider Log = new TplEtwProvider();
@@ -635,13 +648,9 @@ namespace System.Diagnostics.Tracing
 #endif
 
 #if ES_BUILD_AGAINST_DOTNET_V35 || ES_BUILD_PCL || NO_ASYNC_LOCAL
-
+    // In these cases we don't have any Async local support.   Do nothing.   
     internal sealed class AsyncLocalValueChangedArgs<T>
     {
-        public AsyncLocalValueChangedArgs()
-        {
-        }
-
         public T PreviousValue { get { return default(T); } }
         public T CurrentValue { get { return default(T); } }
 
@@ -649,26 +658,13 @@ namespace System.Diagnostics.Tracing
 
     internal sealed class AsyncLocal<T>
     {
-        public AsyncLocal()
-        {
-        }
-
-        public AsyncLocal(Action<AsyncLocalValueChangedArgs<T>> valueChangedHandler)
-        {
-
+        public AsyncLocal(Action<AsyncLocalValueChangedArgs<T>> valueChangedHandler) { 
+            throw new NotImplementedException("AsyncLocal only available on V4.6 and above");
         }
-
         public T Value
         {
-            get
-            {
-                object obj = null;  // TODO FIX 
-                return (obj == null) ? default(T) : (T)obj;
-            }
-            set
-            {
-                // TODO FIX 
-            }
+            get { return default(T); }
+            set { }
         }
     }
 #endif
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/EventCounter.cs b/src/mscorlib/src/System/Diagnostics/Eventing/EventCounter.cs
new file mode 100644 (file)
index 0000000..cad47ee
--- /dev/null
@@ -0,0 +1,432 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Threading;
+#if ES_BUILD_PCL
+    using System.Threading.Tasks;
+#endif
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+    /// <summary>
+    /// Provides the ability to collect statistics through EventSource
+    /// </summary>
+    public class EventCounter
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="EventCounter"/> class.
+        /// </summary>
+        /// <param name="name">The name.</param>
+        /// <param name="eventSource">The event source.</param>
+        public EventCounter(string name, EventSource eventSource)
+        {
+            if (name == null)
+            {
+                throw new ArgumentNullException("name");
+            }
+
+            if (eventSource == null)
+            {
+                throw new ArgumentNullException("eventSource");
+            }
+
+            InitializeBuffer();
+            _name = name;
+            EventCounterGroup.AddEventCounter(eventSource, this);
+        }
+
+        /// <summary>
+        /// Writes the metric.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        public void WriteMetric(float value)
+        {
+            Enqueue(value);
+        }
+
+        #region private implementation
+
+        private readonly string _name;
+
+        #region Buffer Management
+
+        // Values buffering
+        private const int BufferedSize = 10;
+        private const float UnusedBufferSlotValue = float.NegativeInfinity;
+        private const int UnsetIndex = -1;
+        private volatile float[] _bufferedValues; 
+        private volatile int _bufferedValuesIndex;
+
+        private void InitializeBuffer()
+        {
+            _bufferedValues = new float[BufferedSize];
+            for (int i = 0; i < _bufferedValues.Length; i++)
+            {
+                _bufferedValues[i] = UnusedBufferSlotValue;
+            }
+        }
+
+        private void Enqueue(float value)
+        {
+            // It is possible that two threads read the same bufferedValuesIndex, but only one will be able to write the slot, so that is okay.
+            int i = _bufferedValuesIndex;
+            while (true)
+            {
+                float result = Interlocked.CompareExchange(ref _bufferedValues[i], value, UnusedBufferSlotValue);
+                i++;
+                if (_bufferedValues.Length <= i)
+                {
+                    // It is possible that two threads both think the buffer is full, but only one get to actually flush it, the other
+                    // will eventually enter this code path and potentially calling Flushing on a buffer that is not full, and that's okay too.
+                    lock (_bufferedValues)
+                    {
+                        Flush();
+                    }
+                    i = 0;
+                }
+
+                if (result == UnusedBufferSlotValue)
+                {
+                    // CompareExchange succeeded 
+                    _bufferedValuesIndex = i;
+                    return;
+                }
+            }
+        }
+
+        private void Flush()
+        {
+            for (int i = 0; i < _bufferedValues.Length; i++)
+            {
+                var value = Interlocked.Exchange(ref _bufferedValues[i], UnusedBufferSlotValue);
+                if (value != UnusedBufferSlotValue)
+                {
+                    OnMetricWritten(value);
+                }
+            }
+
+            _bufferedValuesIndex = 0;
+        }
+
+        #endregion // Buffer Management
+
+        #region Statistics Calculation
+
+        // Statistics
+        private int _count;
+        private float _sum;
+        private float _sumSquared;
+        private float _min;
+        private float _max;
+
+        private void OnMetricWritten(float value)
+        {
+            _sum += value;
+            _sumSquared += value * value;
+            if (_count == 0 || value > _max)
+            {
+                _max = value;
+            }
+
+            if (_count == 0 || value < _min)
+            {
+                _min = value;
+            }
+
+            _count++;
+        }
+
+        internal EventCounterPayload GetEventCounterPayload()
+        {
+            lock (_bufferedValues)
+            {
+                Flush();
+                EventCounterPayload result = new EventCounterPayload();
+                result.Name = _name;
+                result.Count = _count;
+                result.Mean = _sum / _count;
+                result.StandardDerivation = (float)Math.Sqrt(_sumSquared / _count - _sum * _sum / _count / _count);
+                result.Min = _min;
+                result.Max = _max;
+                ResetStatistics();
+                return result;
+            }
+        }
+
+        private void ResetStatistics()
+        {
+            _count = 0;
+            _sum = 0;
+            _sumSquared = 0;
+            _min = 0;
+            _max = 0;
+        }
+
+        #endregion // Statistics Calculation
+
+        #endregion // private implementation
+    }
+
+    #region internal supporting classes
+
+    [EventData]
+    internal class EventCounterPayload : IEnumerable<KeyValuePair<string, object>>
+    {
+        public string Name { get; set; }
+
+        public float Mean { get; set; }
+
+        public float StandardDerivation { get; set; }
+
+        public int Count { get; set; }
+
+        public float Min { get; set; }
+
+        public float Max { get; set; }
+
+        public float IntervalSec { get; internal set; }
+
+        #region Implementation of the IEnumerable interface
+
+        public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
+        {
+            return ForEnumeration.GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return ForEnumeration.GetEnumerator();
+        }
+
+        private IEnumerable<KeyValuePair<string, object>> ForEnumeration
+        {
+            get
+            {
+                yield return new KeyValuePair<string, object>("Name", Name);
+                yield return new KeyValuePair<string, object>("Mean", Mean);
+                yield return new KeyValuePair<string, object>("StandardDerivation", StandardDerivation);
+                yield return new KeyValuePair<string, object>("Count", Count);
+                yield return new KeyValuePair<string, object>("Min", Min);
+                yield return new KeyValuePair<string, object>("Max", Max);
+            }
+        }
+
+        #endregion // Implementation of the IEnumerable interface
+    }
+
+    internal class EventCounterGroup : IDisposable
+    {
+        private readonly EventSource _eventSource;
+        private readonly int _eventSourceIndex;
+        private readonly List<EventCounter> _eventCounters;
+
+        internal EventCounterGroup(EventSource eventSource, int eventSourceIndex)
+        {
+            _eventSource = eventSource;
+            _eventSourceIndex = eventSourceIndex;
+            _eventCounters = new List<EventCounter>();
+            RegisterCommandCallback();
+        }
+
+        private void Add(EventCounter eventCounter)
+        {
+            _eventCounters.Add(eventCounter);
+        }
+
+        #region EventSource Command Processing
+
+        private void RegisterCommandCallback()
+        {
+            _eventSource.EventCommandExecuted += OnEventSourceCommand;
+        }
+
+        private void OnEventSourceCommand(object sender, EventCommandEventArgs e)
+        {
+            if (e.Command == EventCommand.Enable || e.Command == EventCommand.Update)
+            {
+                string valueStr;
+                float value;
+                if (e.Arguments.TryGetValue("EventCounterIntervalSec", out valueStr) && float.TryParse(valueStr, out value))
+                {
+                    EnableTimer(value);
+                }
+            }
+        }
+
+        #endregion // EventSource Command Processing
+
+        #region Global EventCounterGroup Array management
+
+        private static EventCounterGroup[] s_eventCounterGroups;
+
+        internal static void AddEventCounter(EventSource eventSource, EventCounter eventCounter)
+        {
+            int eventSourceIndex = EventListener.EventSourceIndex(eventSource);
+
+            EventCounterGroup.EnsureEventSourceIndexAvailable(eventSourceIndex);
+            EventCounterGroup eventCounterGroup = GetEventCounterGroup(eventSource);
+            eventCounterGroup.Add(eventCounter);
+        }
+
+        private static void EnsureEventSourceIndexAvailable(int eventSourceIndex)
+        {
+            if (EventCounterGroup.s_eventCounterGroups == null)
+            {
+                EventCounterGroup.s_eventCounterGroups = new EventCounterGroup[eventSourceIndex + 1];
+            }
+            else if (eventSourceIndex >= EventCounterGroup.s_eventCounterGroups.Length)
+            {
+                EventCounterGroup[] newEventCounterGroups = new EventCounterGroup[eventSourceIndex + 1];
+                Array.Copy(EventCounterGroup.s_eventCounterGroups, newEventCounterGroups, EventCounterGroup.s_eventCounterGroups.Length);
+                EventCounterGroup.s_eventCounterGroups = newEventCounterGroups;
+            }
+        }
+
+        private static EventCounterGroup GetEventCounterGroup(EventSource eventSource)
+        {
+            int eventSourceIndex = EventListener.EventSourceIndex(eventSource);
+            EventCounterGroup result = EventCounterGroup.s_eventCounterGroups[eventSourceIndex];
+            if (result == null)
+            {
+                result = new EventCounterGroup(eventSource, eventSourceIndex);
+                EventCounterGroup.s_eventCounterGroups[eventSourceIndex] = result;
+            }
+
+            return result;
+        }
+
+        #endregion // Global EventCounterGroup Array management
+
+        #region Timer Processing
+
+        private DateTime _timeStampSinceCollectionStarted;
+        private int _pollingIntervalInMilliseconds;
+        private Timer _pollingTimer;
+
+        private void EnableTimer(float pollingIntervalInSeconds)
+        {
+            if (pollingIntervalInSeconds == 0)
+            {
+                if (_pollingTimer != null)
+                {
+                    _pollingTimer.Dispose();
+                    _pollingTimer = null;
+                }
+
+                _pollingIntervalInMilliseconds = 0;
+            }
+            else if (_pollingIntervalInMilliseconds == 0 || pollingIntervalInSeconds < _pollingIntervalInMilliseconds)
+            {
+                _pollingIntervalInMilliseconds = (int)(pollingIntervalInSeconds * 1000);
+                if (_pollingTimer != null)
+                {
+                    _pollingTimer.Dispose();
+                    _pollingTimer = null;
+                }
+
+                _timeStampSinceCollectionStarted = DateTime.Now;
+                _pollingTimer = new Timer(OnTimer, null, _pollingIntervalInMilliseconds, _pollingIntervalInMilliseconds);
+            }
+        }
+
+        private void OnTimer(object state)
+        {
+            if (_eventSource.IsEnabled())
+            {
+                DateTime now = DateTime.Now;
+                TimeSpan elapsed = now - _timeStampSinceCollectionStarted;
+                lock (_pollingTimer)
+                {
+                    foreach (var eventCounter in _eventCounters)
+                    {
+                        EventCounterPayload payload = eventCounter.GetEventCounterPayload();
+                        payload.IntervalSec = (float)elapsed.TotalSeconds;
+                        _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new { Payload = payload });
+                    }
+
+
+                    _timeStampSinceCollectionStarted = now;
+                }
+            }
+            else
+            {
+                _pollingTimer.Dispose();
+                _pollingTimer = null;
+                EventCounterGroup.s_eventCounterGroups[_eventSourceIndex] = null;
+            }
+        }
+
+        #region PCL timer hack
+
+#if ES_BUILD_PCL
+    internal delegate void TimerCallback(object state);
+
+        internal sealed class Timer : CancellationTokenSource, IDisposable
+        {
+            private int _period;
+            private TimerCallback _callback;
+            private object _state;
+
+            internal Timer(TimerCallback callback, object state, int dueTime, int period)
+            {
+                _callback = callback;
+                _state = state;
+                _period = period;
+                Schedule(dueTime);
+            }
+
+            private void Schedule(int dueTime)
+            {
+                Task.Delay(dueTime, Token).ContinueWith(OnTimer, null, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);
+            }
+
+            private void OnTimer(Task t, object s)
+            {
+                Schedule(_period);
+                _callback(_state);
+            }
+
+            public new void Dispose() { base.Cancel(); }
+        }
+#endif
+        #endregion // PCL timer hack
+
+        #endregion // Timer Processing
+
+        #region Implementation of the IDisposable interface
+
+        private bool _disposed = false;
+
+        public void Dispose()
+        {
+            Dispose(true);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (_disposed)
+            {
+                return;
+            }
+
+            if (disposing)
+            {
+                if (_pollingTimer != null)
+                {
+                    _pollingTimer.Dispose();
+                    _pollingTimer = null;
+                }
+            }
+
+            _disposed = true;
+        }
+
+        #endregion // Implementation of the IDisposable interface
+    }
+
+    #endregion // internal supporting classes
+}
index 643bc88..7df8150 100644 (file)
@@ -72,12 +72,12 @@ namespace System.Diagnostics.Tracing
         {
             if (id < 0)
             {
-                throw new ArgumentOutOfRangeException("id", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+                throw new ArgumentOutOfRangeException("id", Resources.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
             }
 
             if (id > ushort.MaxValue)
             {
-                throw new ArgumentOutOfRangeException("id", Environment.GetResourceString("ArgumentOutOfRange_NeedValidId", 1, ushort.MaxValue));
+                throw new ArgumentOutOfRangeException("id", Resources.GetResourceString("ArgumentOutOfRange_NeedValidId", 1, ushort.MaxValue));
             }
 
             m_traceloggingId = 0;
@@ -90,19 +90,21 @@ namespace System.Diagnostics.Tracing
 
             if (task < 0)
             {
-                throw new ArgumentOutOfRangeException("task", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+                throw new ArgumentOutOfRangeException("task", Resources.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
             }
 
             if (task > ushort.MaxValue)
             {
-                throw new ArgumentOutOfRangeException("task", Environment.GetResourceString("ArgumentOutOfRange_NeedValidId", 1, ushort.MaxValue));
+                throw new ArgumentOutOfRangeException("task", Resources.GetResourceString("ArgumentOutOfRange_NeedValidId", 1, ushort.MaxValue));
             }
 
             m_task = (ushort)task;
         }
 
-        public int EventId { 
-            get {
+        public int EventId
+        {
+            get
+            {
                 return m_id;
             }
         }
@@ -159,7 +161,7 @@ namespace System.Diagnostics.Tracing
 
         public override int GetHashCode()
         {
-            return m_id ^ m_version ^ m_channel ^ m_level ^ m_opcode ^ m_task ^ (int)m_keywords; 
+            return m_id ^ m_version ^ m_channel ^ m_level ^ m_opcode ^ m_task ^ (int)m_keywords;
         }
 
         public bool Equals(EventDescriptor other)
@@ -185,6 +187,6 @@ namespace System.Diagnostics.Tracing
         public static bool operator !=(EventDescriptor event1, EventDescriptor event2)
         {
             return !event1.Equals(event2);
-        }    
+        }
     }
 }
index cd5b35e..4ffeed3 100644 (file)
@@ -2,6 +2,7 @@
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
 using Microsoft.Win32;
+
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
@@ -18,6 +19,12 @@ using Contract = System.Diagnostics.Contracts.Contract;
 using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
 #endif
 
+#if ES_BUILD_STANDALONE
+using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
+using EventDescriptor = Microsoft.Diagnostics.Tracing.EventDescriptor;
+#endif
+
+
 #if ES_BUILD_AGAINST_DOTNET_V35
 using Microsoft.Internal;       // for Tuple (can't define alias for open generic types so we "use" the whole namespace)
 #endif
@@ -44,7 +51,7 @@ namespace System.Diagnostics.Tracing
     /// controller callback)
     /// </summary>
     [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
-    internal class EventProvider : IDisposable
+    internal partial class EventProvider : IDisposable
     {
         // This is the windows EVENT_DATA_DESCRIPTOR structure.  We expose it because this is what
         // subclasses of EventProvider use when creating efficient (but unsafe) version of
@@ -80,7 +87,9 @@ namespace System.Diagnostics.Tracing
         private byte m_level;                            // Tracing Level
         private long m_anyKeywordMask;                   // Trace Enable Flags
         private long m_allKeywordMask;                   // Match all keyword
+#if ES_SESSION_INFO || FEATURE_ACTIVITYSAMPLING
         private List<SessionInfo> m_liveSessions;        // current live sessions (Tuple<sessionIdBit, etwSessionId>)
+#endif
         private bool m_enabled;                          // Enabled flag from Trace callback
         private Guid m_providerId;                       // Control Guid 
         internal bool m_disposed;                        // when true provider has unregistered
@@ -104,12 +113,12 @@ namespace System.Diagnostics.Tracing
             EventTooBig = 2,
             NullInput = 3,
             TooManyArgs = 4,
-            Other = 5, 
+            Other = 5,
         };
 
         // Because callbacks happen on registration, and we need the callbacks for those setup
         // we can't call Register in the constructor.   
-            //
+        //
         // Note that EventProvider should ONLY be used by EventSource.  In particular because
         // it registers a callback from native code you MUST dispose it BEFORE shutdown, otherwise
         // you may get native callbacks during shutdown when we have destroyed the delegate.  
@@ -135,40 +144,13 @@ namespace System.Diagnostics.Tracing
             uint status;
             m_etwCallback = new UnsafeNativeMethods.ManifestEtw.EtwEnableCallback(EtwEnableCallBack);
 
-            status = EventRegister(ref m_providerId, m_etwCallback); 
+            status = EventRegister(ref m_providerId, m_etwCallback);
             if (status != 0)
             {
                 throw new ArgumentException(Win32Native.GetMessage(unchecked((int)status)));
             }
         }
 
-        [System.Security.SecurityCritical]
-        internal unsafe int SetInformation(
-            UnsafeNativeMethods.ManifestEtw.EVENT_INFO_CLASS eventInfoClass,
-            void* data,
-            int dataSize)
-        {
-            int status = UnsafeNativeMethods.ManifestEtw.ERROR_NOT_SUPPORTED;
-
-            if (!m_setInformationMissing)
-            {
-                try
-                {
-                    status = UnsafeNativeMethods.ManifestEtw.EventSetInformation(
-                        m_regHandle,
-                        eventInfoClass,
-                        data,
-                        dataSize);
-                }
-                catch (TypeLoadException)
-                {
-                    m_setInformationMissing = true;
-                }
-            }
-
-            return status;
-        }
-
         //
         // implement Dispose Pattern to early deregister from ETW insted of waiting for 
         // the finalizer to call deregistration.
@@ -249,20 +231,16 @@ namespace System.Diagnostics.Tracing
                 m_regHandle = 0;
             }
         }
-
-        // <SecurityKernel Critical="True" Ring="0">
-        // <UsesUnsafeCode Name="Parameter filterData of type: Void*" />
-        // <UsesUnsafeCode Name="Parameter callbackContext of type: Void*" />
-        // </SecurityKernel>
+        
         [System.Security.SecurityCritical]
         unsafe void EtwEnableCallBack(
-                        [In] ref System.Guid sourceId,
-                        [In] int controlCode,
-                        [In] byte setLevel,
-                        [In] long anyKeyword,
-                        [In] long allKeyword,
-                        [In] UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData,
-                        [In] void* callbackContext
+                        ref System.Guid sourceId,
+                        int controlCode,
+                        byte setLevel,
+                        long anyKeyword,
+                        long allKeyword,
+                        UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData,
+                        void* callbackContext
                         )
         {
             // This is an optional callback API. We will therefore ignore any failures that happen as a 
@@ -273,6 +251,7 @@ namespace System.Diagnostics.Tracing
                 ControllerCommand command = ControllerCommand.Update;
                 IDictionary<string, string> args = null;
                 bool skipFinalOnControllerCommand = false;
+
                 if (controlCode == UnsafeNativeMethods.ManifestEtw.EVENT_CONTROL_CODE_ENABLE_PROVIDER)
                 {
                     m_enabled = true;
@@ -285,7 +264,7 @@ namespace System.Diagnostics.Tracing
                     // today we use FEATURE_ACTIVITYSAMPLING to determine if this code is there or not.
                     // However we put it in the #if so that we don't lose the fact that this feature
                     // switch is at least partially independent of FEATURE_ACTIVITYSAMPLING
-
+#if ES_SESSION_INFO || FEATURE_ACTIVITYSAMPLING
                     List<Tuple<SessionInfo, bool>> sessionsChanged = GetSessions();
                     foreach (var session in sessionsChanged)
                     {
@@ -326,6 +305,7 @@ namespace System.Diagnostics.Tracing
                         // execute OnControllerCommand once for every session that has changed.
                         OnControllerCommand(command, args, (bEnabling ? sessionChanged : -sessionChanged), etwSessionId);
                     }
+#endif
                 }
                 else if (controlCode == UnsafeNativeMethods.ManifestEtw.EVENT_CONTROL_CODE_DISABLE_PROVIDER)
                 {
@@ -333,7 +313,9 @@ namespace System.Diagnostics.Tracing
                     m_level = 0;
                     m_anyKeywordMask = 0;
                     m_allKeywordMask = 0;
+#if ES_SESSION_INFO || FEATURE_ACTIVITYSAMPLING
                     m_liveSessions = null;
+#endif
                 }
                 else if (controlCode == UnsafeNativeMethods.ManifestEtw.EVENT_CONTROL_CODE_CAPTURE_STATE)
                 {
@@ -365,6 +347,7 @@ namespace System.Diagnostics.Tracing
             return idx;
         }
 
+#if ES_SESSION_INFO || FEATURE_ACTIVITYSAMPLING
         /// <summary>
         /// Determines the ETW sessions that have been added and/or removed to the set of
         /// sessions interested in the current provider. It does so by (1) enumerating over all
@@ -563,6 +546,7 @@ namespace System.Diagnostics.Tracing
 
             return -1;    
         }
+#endif
 
         /// <summary>
         /// Gets any data to be passed from the controller to the provider.  It starts with what is passed
@@ -573,14 +557,15 @@ namespace System.Diagnostics.Tracing
         /// starts, and the command being issued associated with that data.  
         /// </summary>
         [System.Security.SecurityCritical]
-        private unsafe bool GetDataFromController(int etwSessionId, 
-                UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData, out ControllerCommand command, out byte[] data, out int dataStart)
+        private unsafe bool GetDataFromController(int etwSessionId,
+                UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData,
+                out ControllerCommand command, out byte[] data, out int dataStart)
         {
             data = null;
             dataStart = 0;
             if (filterData == null)
             {
-#if !ES_BUILD_PCL && !FEATURE_PAL
+#if (!ES_BUILD_PCL && !PROJECTN && !FEATURE_PAL)
                 string regKey = @"\Microsoft\Windows\CurrentVersion\Winevt\Publishers\{" + m_providerId + "}";
                 if (System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)) == 8)
                     regKey = @"HKEY_LOCAL_MACHINE\Software" + @"\Wow6432Node" + regKey;
@@ -729,7 +714,7 @@ namespace System.Diagnostics.Tracing
 
         --*/
         {
-            Again:
+        Again:
             dataDescriptor->Reserved = 0;
 
             string sRet = data as string;
@@ -1042,7 +1027,7 @@ namespace System.Diagnostics.Tracing
                             dataRefObj.Add(null);
                             ++refObjIndex;
                         }
-                        
+
                         //
                         // now fix any string arguments and set the pointer on the data descriptor 
                         //
@@ -1162,7 +1147,7 @@ namespace System.Diagnostics.Tracing
                                 (EventOpcode)eventDescriptor.Opcode == EventOpcode.Start ||
                                 (EventOpcode)eventDescriptor.Opcode == EventOpcode.Stop);
             }
-
+            
             int status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, dataCount, (EventData*)data);
 
             if (status != 0)
@@ -1182,9 +1167,7 @@ namespace System.Diagnostics.Tracing
             int dataCount,
             IntPtr data)
         {
-            int status;
-
-            status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(
+            int status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(
                 m_regHandle,
                 ref eventDescriptor,
                 activityID,
@@ -1200,7 +1183,6 @@ namespace System.Diagnostics.Tracing
             return true;
         }
 
-
         // These are look-alikes to the Manifest based ETW OS APIs that have been shimmed to work
         // either with Manifest ETW or Classic ETW (if Manifest based ETW is not available).  
         [SecurityCritical]
@@ -1210,7 +1192,7 @@ namespace System.Diagnostics.Tracing
             m_etwCallback = enableCallback;
             return UnsafeNativeMethods.ManifestEtw.EventRegister(ref providerId, enableCallback, null, ref m_regHandle);
         }
-
+        
         [SecurityCritical]
         private uint EventUnregister()
         {
index f6fe526..54bdc41 100644 (file)
@@ -187,16 +187,15 @@ using System.Reflection;
 using System.Resources;
 using System.Security;
 using System.Security.Permissions;
+
 using System.Text;
 using System.Threading;
 using Microsoft.Win32;
 
 #if ES_BUILD_STANDALONE
-using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
 using EventDescriptor = Microsoft.Diagnostics.Tracing.EventDescriptor;
 #else
 using System.Threading.Tasks;
-using EventDescriptor = System.Diagnostics.Tracing.EventDescriptor;
 #endif
 
 using Microsoft.Reflection;
@@ -428,8 +427,9 @@ namespace System.Diagnostics.Tracing
             }
 
             if (name == null)
-                throw new ArgumentException(Environment.GetResourceString("Argument_InvalidTypeName"), "eventSourceType");
-
+            {
+                throw new ArgumentException(Resources.GetResourceString("Argument_InvalidTypeName"), "eventSourceType");
+            }
             return GenerateGuidFromName(name.ToUpperInvariant());       // Make it case insensitive.  
         }
         /// <summary>
@@ -514,115 +514,11 @@ namespace System.Diagnostics.Tracing
 
             // User-defined EventCommands should not conflict with the reserved commands.
             if ((int)command <= (int)EventCommand.Update && (int)command != (int)EventCommand.SendManifest)
-                throw new ArgumentException(Environment.GetResourceString("EventSource_InvalidCommand"), "command");
-
-            eventSource.SendCommand(null, 0, 0, command, true, EventLevel.LogAlways, EventKeywords.None, commandArguments);
-        }
-
-        // ActivityID support (see also WriteEventWithRelatedActivityIdCore)
-        /// <summary>
-        /// When a thread starts work that is on behalf of 'something else' (typically another 
-        /// thread or network request) it should mark the thread as working on that other work.
-        /// This API marks the current thread as working on activity 'activityID'. This API
-        /// should be used when the caller knows the thread's current activity (the one being
-        /// overwritten) has completed. Otherwise, callers should prefer the overload that
-        /// return the oldActivityThatWillContinue (below).
-        /// 
-        /// All events created with the EventSource on this thread are also tagged with the 
-        /// activity ID of the thread. 
-        /// 
-        /// It is common, and good practice after setting the thread to an activity to log an event
-        /// with a 'start' opcode to indicate that precise time/thread where the new activity 
-        /// started.
-        /// </summary>
-        /// <param name="activityId">A Guid that represents the new activity with which to mark 
-        /// the current thread</param>
-        [System.Security.SecuritySafeCritical]
-        public static void SetCurrentThreadActivityId(Guid activityId)
-        {
-#if FEATURE_MANAGED_ETW
-#if FEATURE_ACTIVITYSAMPLING
-            Guid newId = activityId;
-#endif // FEATURE_ACTIVITYSAMPLING
-            // We ignore errors to keep with the convention that EventSources do not throw errors.
-            // Note we can't access m_throwOnWrites because this is a static method.  
-            if (UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
-                UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
-                ref activityId) == 0)
             {
-#if FEATURE_ACTIVITYSAMPLING
-                var activityDying = s_activityDying;
-                if (activityDying != null && newId != activityId)
-                {
-                    if (activityId == Guid.Empty)
-                    {
-                        activityId = FallbackActivityId;
-                    }
-                    // OutputDebugString(string.Format("Activity dying: {0} -> {1}", activityId, newId));
-                    activityDying(activityId);     // This is actually the OLD activity ID.  
-                }
-#endif // FEATURE_ACTIVITYSAMPLING
+                throw new ArgumentException(Resources.GetResourceString("EventSource_InvalidCommand"), "command");
             }
-#endif // FEATURE_MANAGED_ETW
-            if (TplEtwProvider.Log != null)
-                TplEtwProvider.Log.SetActivityId(activityId);
-        }
-
-        /// <summary>
-        /// When a thread starts work that is on behalf of 'something else' (typically another 
-        /// thread or network request) it should mark the thread as working on that other work.
-        /// This API marks the current thread as working on activity 'activityID'. It returns 
-        /// whatever activity the thread was previously marked with. There is a convention that
-        /// callers can assume that callees restore this activity mark before the callee returns. 
-        /// To encourage this this API returns the old activity, so that it can be restored later.
-        /// 
-        /// All events created with the EventSource on this thread are also tagged with the 
-        /// activity ID of the thread. 
-        /// 
-        /// It is common, and good practice after setting the thread to an activity to log an event
-        /// with a 'start' opcode to indicate that precise time/thread where the new activity 
-        /// started.
-        /// </summary>
-        /// <param name="activityId">A Guid that represents the new activity with which to mark 
-        /// the current thread</param>
-        /// <param name="oldActivityThatWillContinue">The Guid that represents the current activity  
-        /// which will continue at some point in the future, on the current thread</param>
-        [System.Security.SecuritySafeCritical]
-        public static void SetCurrentThreadActivityId(Guid activityId, out Guid oldActivityThatWillContinue)
-        {
-            oldActivityThatWillContinue = activityId;
-#if FEATURE_MANAGED_ETW
-            // We ignore errors to keep with the convention that EventSources do not throw errors.
-            // Note we can't access m_throwOnWrites because this is a static method.  
-            UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
-                UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
-                    ref oldActivityThatWillContinue);
-#endif // FEATURE_MANAGED_ETW
-
-            // We don't call the activityDying callback here because the caller has declared that
-            // it is not dying.  
-            if (TplEtwProvider.Log != null)
-                TplEtwProvider.Log.SetActivityId(activityId);
-        }
 
-        /// <summary>
-        /// Retrieves the ETW activity ID associated with the current thread.
-        /// </summary>
-        public static Guid CurrentThreadActivityId
-        {
-            [System.Security.SecuritySafeCritical]
-            get
-            {
-                // We ignore errors to keep with the convention that EventSources do not throw 
-                // errors. Note we can't access m_throwOnWrites because this is a static method.
-                Guid retVal = new Guid();
-#if FEATURE_MANAGED_ETW
-                UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
-                    UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID,
-                    ref retVal);
-#endif // FEATURE_MANAGED_ETW
-                return retVal;
-            }
+            eventSource.SendCommand(null, 0, 0, command, true, EventLevel.LogAlways, EventKeywords.None, commandArguments);
         }
 
 #if !ES_BUILD_STANDALONE
@@ -650,9 +546,11 @@ namespace System.Diagnostics.Tracing
             get
             {
 #pragma warning disable 612, 618
+                int threadID = AppDomain.GetCurrentThreadId();
+                
                 // Managed thread IDs are more aggressively re-used than native thread IDs,
                 // so we'll use the latter...
-                return new Guid(unchecked((uint)AppDomain.GetCurrentThreadId()),
+                return new Guid(unchecked((uint)threadID),
                                 unchecked((ushort)s_currentPid), unchecked((ushort)(s_currentPid >> 16)),
                                 0x94, 0x1b, 0x87, 0xd5, 0xa6, 0x5c, 0x36, 0x64);
 #pragma warning restore 612, 618
@@ -696,7 +594,10 @@ namespace System.Diagnostics.Tracing
         /// <summary>
         /// Displays the name and GUID for the eventSource for debugging purposes.  
         /// </summary>
-        public override string ToString() { return Environment.GetResourceString("EventSource_ToString", Name, Guid); }
+        public override string ToString()
+        {
+            return Resources.GetResourceString("EventSource_ToString", Name, Guid);
+        }
 
         /// <summary>
         /// Fires when a Command (e.g. Enable) comes from a an EventListener.  
@@ -705,11 +606,8 @@ namespace System.Diagnostics.Tracing
         {
             add
             {
-                lock (this)
-                {
-                    m_eventCommandExecuted += value;
-                }
-
+                m_eventCommandExecuted += value;
+             
                 // If we have an EventHandler<EventCommandEventArgs> attached to the EventSource before the first command arrives
                 // It should get a chance to handle the deferred commands.
                 EventCommandEventArgs deferredCommands = m_deferredCommands;
@@ -721,10 +619,7 @@ namespace System.Diagnostics.Tracing
             }
             remove
             {
-                lock (this)
-                {
-                    m_eventCommandExecuted -= value;
-                }
+                m_eventCommandExecuted -= value;
             }
         }
 
@@ -774,10 +669,43 @@ namespace System.Diagnostics.Tracing
         protected EventSource(EventSourceSettings settings, params string[] traits)
         {
             m_config = ValidateSettings(settings);
-            var myType = this.GetType();
-            Initialize(GetGuid(myType), GetName(myType), traits);
+
+            Guid eventSourceGuid;
+            string eventSourceName;
+
+            EventMetadata[] eventDescriptors;
+            byte[] manifest;
+            GetMetadata(out eventSourceGuid, out eventSourceName, out eventDescriptors, out manifest);
+
+            if (eventSourceGuid.Equals(Guid.Empty) || eventSourceName == null)
+            {
+                var myType = this.GetType();
+                eventSourceGuid = GetGuid(myType);
+                eventSourceName = GetName(myType);
+            }
+
+            Initialize(eventSourceGuid, eventSourceName, traits);
         }
 
+        internal virtual void GetMetadata(out Guid eventSourceGuid, out string eventSourceName, out EventMetadata[] eventData, out byte[] manifestBytes)
+        {
+            //
+            // In ProjectN subclasses need to override this method, and return the data from their EventSourceAttribute and EventAttribute annotations.
+            // On other architectures it is a no-op.
+            //
+            // eventDescriptors needs to contain one EventDescriptor for each event; the event's ID should be the same as its index in this array.
+            // manifestBytes is a UTF-8 encoding of the ETW manifest for the type.
+            //
+            // This will be implemented by an IL rewriter, so we can't make this method abstract or the initial build of the subclass would fail.
+            //
+            eventSourceGuid = Guid.Empty;
+            eventSourceName = null;
+            eventData = null;
+            manifestBytes = null;
+
+            return;
+        }
+        
         /// <summary>
         /// This method is called when the eventSource is updated by the controller.  
         /// </summary>
@@ -1222,7 +1150,7 @@ namespace System.Diagnostics.Tracing
                 {
                     Contract.Assert(m_eventData != null);  // You must have initialized this if you enabled the source.
                     if (relatedActivityId != null)
-                        ValidateEventOpcodeForTransfer(ref m_eventData[eventId]);
+                        ValidateEventOpcodeForTransfer(ref m_eventData[eventId], m_eventData[eventId].Name);
 
 #if FEATURE_MANAGED_ETW
                     if (m_eventData[eventId].EnabledForETW)
@@ -1272,7 +1200,7 @@ namespace System.Diagnostics.Tracing
                                     // mask set to 0x0f so, when all ETW sessions want the event we don't need to 
                                     // synthesize a new one
                                     if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
-                                        ThrowEventSourceException();
+                                        ThrowEventSourceException(m_eventData[eventId].Name);
                                 }
                                 else
                                 {
@@ -1292,7 +1220,7 @@ namespace System.Diagnostics.Tracing
                                         unchecked((long)etwSessions.ToEventKeywords() | origKwd));
 
                                     if (!m_provider.WriteEvent(ref desc, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
-                                        ThrowEventSourceException();
+                                        ThrowEventSourceException(m_eventData[eventId].Name);
                                 }
                             }
                             else
@@ -1322,7 +1250,7 @@ namespace System.Diagnostics.Tracing
                         if (!SelfDescribingEvents)
                         {
                             if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
-                                ThrowEventSourceException();
+                                ThrowEventSourceException(m_eventData[eventId].Name);
                         }
                         else
                         {
@@ -1356,7 +1284,7 @@ namespace System.Diagnostics.Tracing
                     if (ex is EventSourceException)
                         throw;
                     else
-                        ThrowEventSourceException(ex);
+                        ThrowEventSourceException(m_eventData[eventId].Name, ex);
                 }
             }
         }
@@ -1471,8 +1399,10 @@ namespace System.Diagnostics.Tracing
             }
         }
 #endif
+
         [SecurityCritical]
         private unsafe void WriteEventRaw(
+            string eventName,
             ref EventDescriptor eventDescriptor,
             Guid* activityID,
             Guid* relatedActivityID,
@@ -1482,12 +1412,12 @@ namespace System.Diagnostics.Tracing
 #if FEATURE_MANAGED_ETW
             if (m_provider == null)
             {
-                ThrowEventSourceException();
+                ThrowEventSourceException(eventName);
             }
             else
             {
                 if (!m_provider.WriteEventRaw(ref eventDescriptor, activityID, relatedActivityID, dataCount, data))
-                    ThrowEventSourceException();
+                    ThrowEventSourceException(eventName);
             }
 #endif // FEATURE_MANAGED_ETW
         }
@@ -1519,13 +1449,19 @@ namespace System.Diagnostics.Tracing
             {
                 m_traits = traits;
                 if (m_traits != null && m_traits.Length % 2 != 0)
-                    throw new ArgumentException(Environment.GetResourceString("TraitEven"), "traits");
+                {
+                    throw new ArgumentException(Resources.GetResourceString("TraitEven"), "traits");
+                }
 
                 if (eventSourceGuid == Guid.Empty)
-                    throw new ArgumentException(Environment.GetResourceString("EventSource_NeedGuid"));
+                {
+                    throw new ArgumentException(Resources.GetResourceString("EventSource_NeedGuid"));
+                }
 
                 if (eventSourceName == null)
-                    throw new ArgumentException(Environment.GetResourceString("EventSource_NeedName"));
+                {
+                    throw new ArgumentException(Resources.GetResourceString("EventSource_NeedName"));
+                }
 
                 m_name = eventSourceName;
                 m_guid = eventSourceGuid;
@@ -1555,7 +1491,7 @@ namespace System.Diagnostics.Tracing
                 // Set m_provider, which allows this.  
                 m_provider = provider;
 
-#if !ES_BUILD_STANDALONE
+#if (!ES_BUILD_STANDALONE && !PROJECTN)
                 // API available on OS >= Win 8 and patched Win 7.
                 // Disable only for FrameworkEventSource to avoid recursion inside exception handling.
                 var osVer = Environment.OSVersion.Version.Major * 10 + Environment.OSVersion.Version.Minor;
@@ -1563,13 +1499,16 @@ namespace System.Diagnostics.Tracing
 #endif
                 {
                     int setInformationResult;
-                    fixed (void* providerMetadata = this.providerMetadata)
-                    {
-                        setInformationResult = m_provider.SetInformation(
-                            UnsafeNativeMethods.ManifestEtw.EVENT_INFO_CLASS.SetTraits,
-                            providerMetadata,
-                            this.providerMetadata.Length);
-                    }
+                    System.Runtime.InteropServices.GCHandle metadataHandle = 
+                        System.Runtime.InteropServices.GCHandle.Alloc(this.providerMetadata, System.Runtime.InteropServices.GCHandleType.Pinned);
+                    IntPtr providerMetadata = metadataHandle.AddrOfPinnedObject();
+
+                    setInformationResult = m_provider.SetInformation(
+                        UnsafeNativeMethods.ManifestEtw.EVENT_INFO_CLASS.SetTraits,
+                        providerMetadata,
+                        (uint)this.providerMetadata.Length);
+
+                    metadataHandle.Free();
                 }
 #endif // FEATURE_MANAGED_ETW
 
@@ -1812,7 +1751,7 @@ namespace System.Diagnostics.Tracing
             // advance to next EventData in array
             ++data;
 
-            Type dataType = m_eventData[eventId].Parameters[parameterId].ParameterType;
+            Type dataType = GetDataType(m_eventData[eventId], parameterId);
 
         Again:
             if (dataType == typeof(IntPtr))
@@ -1906,19 +1845,32 @@ namespace System.Diagnostics.Tracing
             }
             else
             {
-                if (dataType.IsEnum())
+                if (m_EventSourcePreventRecursion && m_EventSourceInDecodeObject)
                 {
-                    dataType = Enum.GetUnderlyingType(dataType);
-                    goto Again;
+                    return null;
                 }
 
-                // TODO FIX NOW Assuming that it is a string at this point is really likely to be fragile
-                // We should do something better.   
+                try
+                {
+                    m_EventSourceInDecodeObject = true;
 
-                // Everything else is marshaled as a string.
-                // ETW strings are NULL-terminated, so marshal everything up to the first
-                // null in the string.
-                return System.Runtime.InteropServices.Marshal.PtrToStringUni(dataPointer);
+                    if (dataType.IsEnum())
+                    {
+                        dataType = Enum.GetUnderlyingType(dataType);
+                        goto Again;
+                    }
+
+
+                    // Everything else is marshaled as a string.
+                    // ETW strings are NULL-terminated, so marshal everything up to the first
+                    // null in the string.
+                    return System.Runtime.InteropServices.Marshal.PtrToStringUni(dataPointer);
+
+                }
+                finally
+                {
+                    m_EventSourceInDecodeObject = false;
+                }
             }
         }
 
@@ -1946,7 +1898,7 @@ namespace System.Diagnostics.Tracing
                     Contract.Assert(m_eventData != null);  // You must have initialized this if you enabled the source.  
                     if (childActivityID != null)
                     {
-                        ValidateEventOpcodeForTransfer(ref m_eventData[eventId]);
+                        ValidateEventOpcodeForTransfer(ref m_eventData[eventId], m_eventData[eventId].Name);
 
                         // If you use WriteEventWithRelatedActivityID you MUST declare the first argument to be a GUID 
                         // with the name 'relatedActivityID, and NOT pass this argument to the WriteEvent method.  
@@ -1958,7 +1910,7 @@ namespace System.Diagnostics.Tracing
                         // which would cause a cryptic IndexOutOfRangeException later if we don't catch it here.
                         if (!m_eventData[eventId].HasRelatedActivityID)
                         {
-                            throw new ArgumentException(Environment.GetResourceString("EventSource_NoRelatedActivityId"));
+                            throw new ArgumentException(Resources.GetResourceString("EventSource_NoRelatedActivityId"));
                         }
                     }
 
@@ -2007,7 +1959,7 @@ namespace System.Diagnostics.Tracing
                                     // mask set to 0x0f so, when all ETW sessions want the event we don't need to 
                                     // synthesize a new one
                                     if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, childActivityID, args))
-                                        ThrowEventSourceException();
+                                        ThrowEventSourceException(m_eventData[eventId].Name);
                                 }
                                 else
                                 {
@@ -2024,7 +1976,7 @@ namespace System.Diagnostics.Tracing
                                         unchecked((long)(ulong)etwSessions | origKwd));
 
                                     if (!m_provider.WriteEvent(ref desc, pActivityId, childActivityID, args))
-                                        ThrowEventSourceException();
+                                        ThrowEventSourceException(m_eventData[eventId].Name);
                                 }
                             }
                             else
@@ -2054,7 +2006,7 @@ namespace System.Diagnostics.Tracing
                         if (!SelfDescribingEvents)
                         {
                             if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, childActivityID, args))
-                                ThrowEventSourceException();
+                                ThrowEventSourceException(m_eventData[eventId].Name);
                         }
                         else
                         {
@@ -2082,7 +2034,7 @@ namespace System.Diagnostics.Tracing
 #endif // FEATURE_MANAGED_ETW
                     if (m_Dispatchers != null && m_eventData[eventId].EnabledForAnyListener)
                     {
-#if !ES_BUILD_STANDALONE
+#if (!ES_BUILD_STANDALONE && !PROJECTN)
                         // Maintain old behavior - object identity is preserved
                         if (AppContextSwitches.PreserveEventListnerObjectIdentity)
                         {
@@ -2101,7 +2053,7 @@ namespace System.Diagnostics.Tracing
                     if (ex is EventSourceException)
                         throw;
                     else
-                        ThrowEventSourceException(ex);
+                        ThrowEventSourceException(m_eventData[eventId].Name, ex);
                 }
             }
         }
@@ -2133,7 +2085,7 @@ namespace System.Diagnostics.Tracing
         /// <param name="args"></param>
         private void LogEventArgsMismatches(ParameterInfo[] infos, object[] args)
         {
-#if !ES_BUILD_PCL
+#if (!ES_BUILD_PCL && !PROJECTN)
             // It would be nice to have this on PCL builds, but it would be pointless since there isn't support for 
             // writing to the debugger log on PCL.
             bool typesMatch = args.Length == infos.Length;
@@ -2159,7 +2111,7 @@ namespace System.Diagnostics.Tracing
 
             if (!typesMatch)
             {
-                System.Diagnostics.Debugger.Log(0, null, Environment.GetResourceString("EventSource_VarArgsParameterMismatch") + "\r\n");
+                System.Diagnostics.Debugger.Log(0, null, Resources.GetResourceString("EventSource_VarArgsParameterMismatch") + "\r\n");
             }
 #endif //!ES_BUILD_PCL
         }
@@ -2167,10 +2119,11 @@ namespace System.Diagnostics.Tracing
         [SecurityCritical]
         unsafe private void WriteToAllListeners(int eventId, Guid* childActivityID, int eventDataCount, EventSource.EventData* data)
         {
-            int paramCount = m_eventData[eventId].Parameters.Length;
+            int paramCount = GetParameterCount(m_eventData[eventId]);
+            
             if (eventDataCount != paramCount)
             {
-                ReportOutOfBandMessage(Environment.GetResourceString("EventSource_EventParametersMismatch", eventId, eventDataCount, paramCount), true);
+                ReportOutOfBandMessage(Resources.GetResourceString("EventSource_EventParametersMismatch", eventId, eventDataCount, paramCount), true);
                 paramCount = Math.Min(paramCount, eventDataCount);
             }
 
@@ -2238,7 +2191,7 @@ namespace System.Diagnostics.Tracing
                 throw new EventSourceException(lastThrownException);
             }
         }
-
+        
         [SecuritySafeCritical]
         [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
         private unsafe void WriteEventString(EventLevel level, long keywords, string msgString)
@@ -2443,7 +2396,7 @@ namespace System.Diagnostics.Tracing
 
         }
         [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
-        private void ThrowEventSourceException(Exception innerEx = null)
+        private void ThrowEventSourceException(string eventName, Exception innerEx = null)
         {
             // If we fail during out of band logging we may end up trying 
             // to throw another EventSourceException, thus hitting a StackOverflowException. 
@@ -2453,31 +2406,37 @@ namespace System.Diagnostics.Tracing
             try
             {
                 m_EventSourceExceptionRecurenceCount++;
+                
+                string errorPrefix = "EventSourceException";
+                if(eventName != null)
+                {
+                    errorPrefix += " while processing event \"" + eventName + "\"";
+                }
 
                 // TODO Create variations of EventSourceException that indicate more information using the error code.
                 switch (EventProvider.GetLastWriteEventError())
                 {
                     case EventProvider.WriteEventErrorCode.EventTooBig:
-                        ReportOutOfBandMessage("EventSourceException: " + Environment.GetResourceString("EventSource_EventTooBig"), true);
-                        if (ThrowOnEventWriteErrors) throw new EventSourceException(Environment.GetResourceString("EventSource_EventTooBig"), innerEx);
+                        ReportOutOfBandMessage(errorPrefix + ": " + Resources.GetResourceString("EventSource_EventTooBig"), true);
+                        if (ThrowOnEventWriteErrors) throw new EventSourceException(Resources.GetResourceString("EventSource_EventTooBig"), innerEx);
                         break;
                     case EventProvider.WriteEventErrorCode.NoFreeBuffers:
-                        ReportOutOfBandMessage("EventSourceException: " + Environment.GetResourceString("EventSource_NoFreeBuffers"), true);
-                        if (ThrowOnEventWriteErrors) throw new EventSourceException(Environment.GetResourceString("EventSource_NoFreeBuffers"), innerEx);
+                        ReportOutOfBandMessage(errorPrefix + ": " + Resources.GetResourceString("EventSource_NoFreeBuffers"), true);
+                        if (ThrowOnEventWriteErrors) throw new EventSourceException(Resources.GetResourceString("EventSource_NoFreeBuffers"), innerEx);
                         break;
                     case EventProvider.WriteEventErrorCode.NullInput:
-                        ReportOutOfBandMessage("EventSourceException: " + Environment.GetResourceString("EventSource_NullInput"), true);
-                        if (ThrowOnEventWriteErrors) throw new EventSourceException(Environment.GetResourceString("EventSource_NullInput"), innerEx);
+                        ReportOutOfBandMessage(errorPrefix + ": " + Resources.GetResourceString("EventSource_NullInput"), true);
+                        if (ThrowOnEventWriteErrors) throw new EventSourceException(Resources.GetResourceString("EventSource_NullInput"), innerEx);
                         break;
                     case EventProvider.WriteEventErrorCode.TooManyArgs:
-                        ReportOutOfBandMessage("EventSourceException: " + Environment.GetResourceString("EventSource_TooManyArgs"), true);
-                        if (ThrowOnEventWriteErrors) throw new EventSourceException(Environment.GetResourceString("EventSource_TooManyArgs"), innerEx);
+                        ReportOutOfBandMessage(errorPrefix + ": " + Resources.GetResourceString("EventSource_TooManyArgs"), true);
+                        if (ThrowOnEventWriteErrors) throw new EventSourceException(Resources.GetResourceString("EventSource_TooManyArgs"), innerEx);
                         break;
                     default:
                         if (innerEx != null)
-                            ReportOutOfBandMessage("EventSourceException: " + innerEx.GetType() + ":" + innerEx.Message, true);
+                            ReportOutOfBandMessage(errorPrefix + ": " + innerEx.GetType() + ":" + innerEx.Message, true);
                         else
-                            ReportOutOfBandMessage("EventSourceException", true);
+                            ReportOutOfBandMessage(errorPrefix, true);
                         if (ThrowOnEventWriteErrors) throw new EventSourceException(innerEx);
                         break;
                 }
@@ -2488,13 +2447,13 @@ namespace System.Diagnostics.Tracing
             }
         }
 
-        private void ValidateEventOpcodeForTransfer(ref EventMetadata eventData)
+        private void ValidateEventOpcodeForTransfer(ref EventMetadata eventData, string eventName)
         {
             if ((EventOpcode)eventData.Descriptor.Opcode != EventOpcode.Send &&
                 (EventOpcode)eventData.Descriptor.Opcode != EventOpcode.Receive && 
                 (EventOpcode)eventData.Descriptor.Opcode != EventOpcode.Start)
             {
-                ThrowEventSourceException();
+                ThrowEventSourceException(eventName);
             }
         }
 
@@ -2502,11 +2461,11 @@ namespace System.Diagnostics.Tracing
         {
             if (opcode == EventOpcode.Info && eventName != null)
             {
-                if (eventName.EndsWith(s_ActivityStartSuffix))
+                if (eventName.EndsWith(s_ActivityStartSuffix, StringComparison.Ordinal))
                 {
                     return EventOpcode.Start;
                 }
-                else if (eventName.EndsWith(s_ActivityStopSuffix))
+                else if (eventName.EndsWith(s_ActivityStopSuffix, StringComparison.Ordinal))
                 {
                     return EventOpcode.Stop;
                 }
@@ -2542,7 +2501,7 @@ namespace System.Diagnostics.Tracing
         /// descriptor as well as some stuff we added specifically for EventSource. see the
         /// code:m_eventData for where we use this.  
         /// </summary>
-        internal struct EventMetadata
+        internal partial struct EventMetadata
         {
             public EventDescriptor Descriptor;
             public EventTags Tags;
@@ -2563,6 +2522,10 @@ namespace System.Diagnostics.Tracing
 
             public TraceLoggingEventTypes TraceLoggingEventTypes;
             public EventActivityOptions ActivityOptions;
+            
+#if PROJECTN
+            public EventParameterType[] ParameterTypes;
+#endif
         };
 
         // This is the internal entry point that code:EventListeners call when wanting to send a command to a
@@ -2642,7 +2605,9 @@ namespace System.Diagnostics.Tracing
                 // Find the per-EventSource dispatcher corresponding to registered dispatcher
                 commandArgs.dispatcher = GetDispatcher(commandArgs.listener);
                 if (commandArgs.dispatcher == null && commandArgs.listener != null)     // dispatcher == null means ETW dispatcher
-                    throw new ArgumentException(Environment.GetResourceString("EventSource_ListenerNotFound"));
+                {
+                    throw new ArgumentException(Resources.GetResourceString("EventSource_ListenerNotFound"));
+                }
 
                 if (commandArgs.Arguments == null)
                     commandArgs.Arguments = new Dictionary<string, string>();
@@ -2720,7 +2685,7 @@ namespace System.Diagnostics.Tracing
 
                         if (commandArgs.listener == null && commandArgs.Arguments.Count > 0 && commandArgs.perEventSourceSessionId != sessionIdBit)
                         {
-                            throw new ArgumentException(Environment.GetResourceString("EventSource_SessionIdError",
+                            throw new ArgumentException(Resources.GetResourceString("EventSource_SessionIdError",
                                                     commandArgs.perEventSourceSessionId + SessionMask.SHIFT_SESSION_TO_KEYWORD,
                                                         sessionIdBit + SessionMask.SHIFT_SESSION_TO_KEYWORD));
                         }
@@ -3042,10 +3007,31 @@ namespace System.Diagnostics.Tracing
 #endif
             if (m_eventData == null)
             {
-                Contract.Assert(m_rawManifest == null);
-                m_rawManifest = CreateManifestAndDescriptors(this.GetType(), Name, this);
-                Contract.Assert(m_eventData != null);
+                Guid eventSourceGuid = Guid.Empty;
+                string eventSourceName = null;
+                EventMetadata[] eventData = null;
+                byte[] manifest = null;
+
+                // Try the GetMetadata provided by the ILTransform in ProjectN. The default sets all to null, and in that case we fall back
+                // to the reflection approach.
+                GetMetadata(out eventSourceGuid, out eventSourceName, out eventData, out manifest);
 
+                if (eventSourceGuid.Equals(Guid.Empty) || eventSourceName == null || eventData == null || manifest == null)
+                {
+                    // GetMetadata failed, so we have to set it via reflection.
+                    Contract.Assert(m_rawManifest == null);
+                    m_rawManifest = CreateManifestAndDescriptors(this.GetType(), Name, this);
+                    Contract.Assert(m_eventData != null);
+
+                }
+                else
+                {
+                    // GetMetadata worked, so set the fields as appropriate.
+                    m_name = eventSourceName;
+                    m_guid = eventSourceGuid;
+                    m_eventData = eventData;
+                    m_rawManifest = manifest;
+                }
                 // TODO Enforce singleton pattern 
                 foreach (WeakReference eventSourceRef in EventListener.s_EventSources)
                 {
@@ -3053,7 +3039,9 @@ namespace System.Diagnostics.Tracing
                     if (eventSource != null && eventSource.Guid == m_guid && !eventSource.IsDisposed)
                     {
                         if (eventSource != this)
-                            throw new ArgumentException(Environment.GetResourceString("EventSource_EventSourceGuidInUse", m_guid));
+                        {
+                            throw new ArgumentException(Resources.GetResourceString("EventSource_EventSourceGuidInUse", m_guid));
+                        }
                     }
                 }
 
@@ -3104,6 +3092,7 @@ namespace System.Diagnostics.Tracing
                 envelope.ChunkNumber = 0;
 
                 EventProvider.EventData* dataDescrs = stackalloc EventProvider.EventData[2];
+
                 dataDescrs[0].Ptr = (ulong)&envelope;
                 dataDescrs[0].Size = (uint)sizeof(ManifestEnvelope);
                 dataDescrs[0].Reserved = 0;
@@ -3134,7 +3123,7 @@ namespace System.Diagnostics.Tracing
                             }
                             success = false;
                             if (ThrowOnEventWriteErrors)
-                                ThrowEventSourceException();
+                                ThrowEventSourceException("SendManifest");
                             break;
                         }
                     }
@@ -3147,7 +3136,7 @@ namespace System.Diagnostics.Tracing
             return success;
         }
 
-#if ES_BUILD_PCL
+#if (ES_BUILD_PCL || PROJECTN)
         internal static Attribute GetCustomAttributeHelper(Type type, Type attributeType, EventManifestOptions flags = EventManifestOptions.None)
         {
             return GetCustomAttributeHelper(type.GetTypeInfo(), attributeType, flags);
@@ -3170,7 +3159,7 @@ namespace System.Diagnostics.Tracing
                 return firstAttribute;
             }
 
-#if !ES_BUILD_PCL
+#if (!ES_BUILD_PCL && !PROJECTN)
             // In the reflection only context, we have to do things by hand.
             string fullTypeNameToFind = attributeType.FullName;
 
@@ -3218,8 +3207,8 @@ namespace System.Diagnostics.Tracing
             }
 
             return null;
-#else // ES_BUILD_PCL
-            throw new ArgumentException(Environment.GetResourceString("EventSource", "EventSource_PCLPlatformNotSupportedReflection"));
+#else // ES_BUILD_PCL && PROJECTN
+            throw new ArgumentException(Resources.GetResourceString("EventSource", "EventSource_PCLPlatformNotSupportedReflection"));
 #endif
         }
 
@@ -3335,9 +3324,13 @@ namespace System.Diagnostics.Tracing
                     bool typeMatch = GetEventSourceBaseType(eventSourceType, (flags & EventManifestOptions.AllowEventSourceOverride) != 0, eventSourceType.Assembly().ReflectionOnly()) != null;
 
                     if (!typeMatch)
-                        manifest.ManifestError(Environment.GetResourceString("EventSource_TypeMustDeriveFromEventSource"));
+                    {
+                        manifest.ManifestError(Resources.GetResourceString("EventSource_TypeMustDeriveFromEventSource"));
+                    }
                     if (!eventSourceType.IsAbstract() && !eventSourceType.IsSealed())
-                        manifest.ManifestError(Environment.GetResourceString("EventSource_TypeMustBeSealedOrAbstract"));
+                    {
+                        manifest.ManifestError(Resources.GetResourceString("EventSource_TypeMustBeSealedOrAbstract"));
+                    }
                 }
 
                 // Collect task, opcode, keyword and channel information
@@ -3352,7 +3345,7 @@ namespace System.Diagnostics.Tracing
                     {
                         if (eventSourceType.IsAbstract())
                         {
-                            manifest.ManifestError(Environment.GetResourceString("EventSource_AbstractMustNotDeclareKTOC", nestedType.Name));
+                            manifest.ManifestError(Resources.GetResourceString("EventSource_AbstractMustNotDeclareKTOC", nestedType.Name));
                         }
                         else
                         {
@@ -3394,7 +3387,9 @@ namespace System.Diagnostics.Tracing
                         if (eventSourceType.IsAbstract())
                         {
                             if (eventAttribute != null)
-                                manifest.ManifestError(Environment.GetResourceString("EventSource_AbstractMustNotDeclareEventMethods", method.Name, eventAttribute.EventId));
+                            {
+                                manifest.ManifestError(Resources.GetResourceString("EventSource_AbstractMustNotDeclareEventMethods", method.Name, eventAttribute.EventId));
+                            }
                             continue;
                         }
                         else if (eventAttribute == null)
@@ -3422,11 +3417,13 @@ namespace System.Diagnostics.Tracing
                         }
                         else if (eventAttribute.EventId <= 0)
                         {
-                            manifest.ManifestError(Environment.GetResourceString("EventSource_NeedPositiveId", method.Name), true);
+                            manifest.ManifestError(Resources.GetResourceString("EventSource_NeedPositiveId", method.Name), true);
                             continue;   // don't validate anything else for this event
                         }
                         if (method.Name.LastIndexOf('.') >= 0)
-                            manifest.ManifestError(Environment.GetResourceString("EventSource_EventMustNotBeExplicitImplementation", method.Name, eventAttribute.EventId));
+                        {
+                            manifest.ManifestError(Resources.GetResourceString("EventSource_EventMustNotBeExplicitImplementation", method.Name, eventAttribute.EventId));
+                        }
 
                         eventId++;
                         string eventName = method.Name;
@@ -3480,7 +3477,9 @@ namespace System.Diagnostics.Tracing
                                         }
                                     }
                                     if (noTask && (flags & EventManifestOptions.Strict) != 0)        // Throw an error if we can compatibly.   
-                                        throw new ArgumentException(Environment.GetResourceString("EventSource_StopsFollowStarts"));
+                                    {
+                                        throw new ArgumentException(Resources.GetResourceString("EventSource_StopsFollowStarts"));
+                                    }
                                 }
                             }
                         }
@@ -3632,7 +3631,7 @@ namespace System.Diagnostics.Tracing
 #endif
             return;
         Error:
-            manifest.ManifestError(Environment.GetResourceString("EventSource_EnumKindMismatch", staticField.Name, staticField.FieldType.Name, providerEnumKind));
+            manifest.ManifestError(Resources.GetResourceString("EventSource_EnumKindMismatch", staticField.Name, staticField.FieldType.Name, providerEnumKind));
         }
 
         // Helper used by code:CreateManifestAndDescriptors to add a code:EventData descriptor for a method
@@ -3655,9 +3654,9 @@ namespace System.Diagnostics.Tracing
 #if FEATURE_MANAGED_ETW_CHANNELS
                     (byte)eventAttribute.Channel,
 #else
- (byte)0,
                   (byte)0,
 #endif
- (byte)eventAttribute.Level,
                   (byte)eventAttribute.Level,
                     (byte)eventAttribute.Opcode,
                     (int)eventAttribute.Task,
                     unchecked((long)((ulong)eventAttribute.Keywords | SessionMask.All.ToEventKeywords())));
@@ -3688,7 +3687,7 @@ namespace System.Diagnostics.Tracing
                 eventData = newValues;
             }
         }
-        
+
         // Helper used by code:EventListener.AddEventSource and code:EventListener.EventListener
         // when a listener gets attached to a eventSource
         internal void AddListener(EventListener listener)
@@ -3714,12 +3713,12 @@ namespace System.Diagnostics.Tracing
             int eventArg = GetHelperCallFirstArg(method);
             if (eventArg >= 0 && evtId != eventArg)
             {
-                manifest.ManifestError(Environment.GetResourceString("EventSource_MismatchIdToWriteEvent", evtName, evtId, eventArg), true);
+                manifest.ManifestError(Resources.GetResourceString("EventSource_MismatchIdToWriteEvent", evtName, evtId, eventArg), true);
             }
 
             if (evtId < eventData.Length && eventData[evtId].Descriptor.EventId != 0)
             {
-                manifest.ManifestError(Environment.GetResourceString("EventSource_EventIdReused", evtName, evtId, eventData[evtId].Name), true);
+                manifest.ManifestError(Resources.GetResourceString("EventSource_EventIdReused", evtName, evtId, eventData[evtId].Name), true);
             }
 
             // We give a task to things if they don't have one.  
@@ -3733,9 +3732,8 @@ namespace System.Diagnostics.Tracing
 
                 if (eventData[idx].Descriptor.Task == (int)eventAttribute.Task && eventData[idx].Descriptor.Opcode == (int)eventAttribute.Opcode)
                 {
-                    manifest.ManifestError(Environment.GetResourceString("EventSource_TaskOpcodePairReused",
+                    manifest.ManifestError(Resources.GetResourceString("EventSource_TaskOpcodePairReused",
                                             evtName, evtId, eventData[idx].Name, idx));
-
                     // If we are not strict stop on first error.   We have had problems with really large providers taking forever.  because of many errors.  
                     if ((options & EventManifestOptions.Strict) == 0)
                         break;
@@ -3758,7 +3756,9 @@ namespace System.Diagnostics.Tracing
                         failure = true;
                 }
                 if (failure)
-                    manifest.ManifestError(Environment.GetResourceString("EventSource_EventMustHaveTaskIfNonDefaultOpcode", evtName, evtId));
+                {
+                    manifest.ManifestError(Resources.GetResourceString("EventSource_EventMustHaveTaskIfNonDefaultOpcode", evtName, evtId));
+                }
             }
 
             // If we ever want to enforce the rule: MethodName = TaskName + OpcodeName here's how:
@@ -3767,14 +3767,16 @@ namespace System.Diagnostics.Tracing
             // taskName & opcodeName could be passed in by the caller which has opTab & taskTab handy
             // if (!(((int)eventAttribute.Opcode == 0 && evtName == taskName) || (evtName == taskName+opcodeName)))
             // {
-            //     throw new WarningException(Environment.GetResourceString("EventSource_EventNameDoesNotEqualTaskPlusOpcode"));
+            //     throw new WarningException(Resources.GetResourceString("EventSource_EventNameDoesNotEqualTaskPlusOpcode"));
             // }
 
             if (eventsByName == null)
                 eventsByName = new Dictionary<string, string>();
 
             if (eventsByName.ContainsKey(evtName))
-                manifest.ManifestError(Environment.GetResourceString("EventSource_EventNameReused", evtName), true);
+            {
+                manifest.ManifestError(Resources.GetResourceString("EventSource_EventNameReused", evtName), true);
+            }
 
             eventsByName[evtName] = evtName;
         }
@@ -3795,7 +3797,7 @@ namespace System.Diagnostics.Tracing
         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Switch statement is clearer than alternatives")]
         static private int GetHelperCallFirstArg(MethodInfo method)
         {
-#if !ES_BUILD_PCL
+#if (!ES_BUILD_PCL && !PROJECTN)
             // Currently searches for the following pattern
             // 
             // ...     // CAN ONLY BE THE INSTRUCTIONS BELOW
@@ -3936,9 +3938,9 @@ namespace System.Diagnostics.Tracing
         {
             try
             {
-#if !ES_BUILD_PCL
+#if (!ES_BUILD_PCL && !PROJECTN)
                 // send message to debugger without delay
-                System.Diagnostics.Debugger.Log(0, null, msg + "\r\n");
+                System.Diagnostics.Debugger.Log(0, null, String.Format("EventSource Error: {0}{1}", msg , Environment.NewLine));
 #endif
 
                 // Send it to all listeners.
@@ -3963,7 +3965,9 @@ namespace System.Diagnostics.Tracing
             var evtFormatMask = EventSourceSettings.EtwManifestEventFormat |
                                 EventSourceSettings.EtwSelfDescribingEventFormat;
             if ((settings & evtFormatMask) == evtFormatMask)
-                throw new ArgumentException(Environment.GetResourceString("EventSource_InvalidEventFormat"), "settings");
+            {
+                throw new ArgumentException(Resources.GetResourceString("EventSource_InvalidEventFormat"), "settings");
+            }
 
             // If you did not explicitly ask for manifest, you get self-describing.  
             if ((settings & evtFormatMask) == 0)
@@ -4080,6 +4084,9 @@ namespace System.Diagnostics.Tracing
         [ThreadStatic]
         private static byte m_EventSourceExceptionRecurenceCount = 0; // current recursion count inside ThrowEventSourceException
 
+        [ThreadStatic]
+        private static bool m_EventSourceInDecodeObject = false;
+
 #if FEATURE_MANAGED_ETW_CHANNELS
         internal volatile ulong[] m_channelData;
 #endif
@@ -4177,7 +4184,7 @@ namespace System.Diagnostics.Tracing
     /// created.
     /// </para>
     /// </summary>
-    public abstract class EventListener : IDisposable
+    public class EventListener : IDisposable
     {
         private event EventHandler<EventSourceCreatedEventArgs> _EventSourceCreated;
 
@@ -4217,7 +4224,7 @@ namespace System.Diagnostics.Tracing
         /// Create a new EventListener in which all events start off turned off (use EnableEvents to turn
         /// them on).  
         /// </summary>
-        protected EventListener()
+        public EventListener()
         {
             // This will cause the OnEventSourceCreated callback to fire. 
             CallBackForExistingEventSources(true, (obj, args) => args.EventSource.AddListener(this) ); 
@@ -4409,7 +4416,7 @@ namespace System.Diagnostics.Tracing
                 if (!s_EventSourceShutdownRegistered)
                 {
                     s_EventSourceShutdownRegistered = true;
-#if !ES_BUILD_PCL && !FEATURE_CORECLR
+#if (!ES_BUILD_PCL && !FEATURE_CORECLR && !PROJECTN)
                     AppDomain.CurrentDomain.ProcessExit += DisposeOnShutdown;
                     AppDomain.CurrentDomain.DomainUnload += DisposeOnShutdown;
 #endif
@@ -4585,7 +4592,9 @@ namespace System.Diagnostics.Tracing
             {
                 // Disallow creating EventListener reentrancy. 
                 if (s_CreatingListener)
-                    throw new InvalidOperationException(Environment.GetResourceString("EventSource_ListenerCreatedInsideCallback"));
+                {
+                    throw new InvalidOperationException(Resources.GetResourceString("EventSource_ListenerCreatedInsideCallback"));
+                }
 
                 try
                 {
@@ -5931,8 +5940,8 @@ namespace System.Diagnostics.Tracing
         private uint m_mask;
 
         internal const int SHIFT_SESSION_TO_KEYWORD = 44;         // bits 44-47 inclusive are reserved
-        internal const uint MASK = 0x0fU;      // the mask of 4 reserved bits
-        internal const uint MAX = 4;          // maximum number of simultaneous ETW sessions supported
+        internal const uint MASK = 0x0fU;                         // the mask of 4 reserved bits
+        internal const uint MAX = 4;                              // maximum number of simultaneous ETW sessions supported
     }
 
     /// <summary>
@@ -6004,7 +6013,7 @@ namespace System.Diagnostics.Tracing
     /// ManifestBuilder is designed to isolate the details of the message of the event from the
     /// rest of EventSource.  This one happens to create XML. 
     /// </summary>
-    internal class ManifestBuilder
+    internal partial class ManifestBuilder
     {
         /// <summary>
         /// Build a manifest for 'providerName' with the given GUID, which will be packaged into 'dllName'.
@@ -6045,10 +6054,14 @@ namespace System.Diagnostics.Tracing
             if ((flags & EventManifestOptions.Strict) != 0)
             {
                 if (value <= 10 || value >= 239)
-                    ManifestError(Environment.GetResourceString("EventSource_IllegalOpcodeValue", name, value));
+                {
+                    ManifestError(Resources.GetResourceString("EventSource_IllegalOpcodeValue", name, value));
+                }
                 string prevName;
                 if (opcodeTab.TryGetValue(value, out prevName) && !name.Equals(prevName, StringComparison.Ordinal))
-                    ManifestError(Environment.GetResourceString("EventSource_OpcodeCollision", name, prevName, value));
+                {
+                    ManifestError(Resources.GetResourceString("EventSource_OpcodeCollision", name, prevName, value));
+                }
             }
             opcodeTab[value] = name;
         }
@@ -6057,10 +6070,14 @@ namespace System.Diagnostics.Tracing
             if ((flags & EventManifestOptions.Strict) != 0)
             {
                 if (value <= 0 || value >= 65535)
-                    ManifestError(Environment.GetResourceString("EventSource_IllegalTaskValue", name, value));
+                {
+                    ManifestError(Resources.GetResourceString("EventSource_IllegalTaskValue", name, value));
+                }
                 string prevName;
                 if (taskTab != null && taskTab.TryGetValue(value, out prevName) && !name.Equals(prevName, StringComparison.Ordinal))
-                    ManifestError(Environment.GetResourceString("EventSource_TaskCollision", name, prevName, value));
+                {
+                    ManifestError(Resources.GetResourceString("EventSource_TaskCollision", name, prevName, value));
+                }
             }
             if (taskTab == null)
                 taskTab = new Dictionary<int, string>();
@@ -6069,14 +6086,20 @@ namespace System.Diagnostics.Tracing
         public void AddKeyword(string name, ulong value)
         {
             if ((value & (value - 1)) != 0)   // Is it a power of 2?
-                ManifestError(Environment.GetResourceString("EventSource_KeywordNeedPowerOfTwo", "0x" + value.ToString("x", CultureInfo.CurrentCulture), name), true);
+            {
+                ManifestError(Resources.GetResourceString("EventSource_KeywordNeedPowerOfTwo", "0x" + value.ToString("x", CultureInfo.CurrentCulture), name), true);
+            }
             if ((flags & EventManifestOptions.Strict) != 0)
             {
                 if (value >= 0x0000100000000000UL && !name.StartsWith("Session", StringComparison.Ordinal))
-                    ManifestError(Environment.GetResourceString("EventSource_IllegalKeywordsValue", name, "0x" + value.ToString("x", CultureInfo.CurrentCulture)));
+                {
+                    ManifestError(Resources.GetResourceString("EventSource_IllegalKeywordsValue", name, "0x" + value.ToString("x", CultureInfo.CurrentCulture)));
+                }
                 string prevName;
                 if (keywordTab != null && keywordTab.TryGetValue(value, out prevName) && !name.Equals(prevName, StringComparison.Ordinal))
-                    ManifestError(Environment.GetResourceString("EventSource_KeywordCollision", name, prevName, "0x" + value.ToString("x", CultureInfo.CurrentCulture)));
+                {
+                    ManifestError(Resources.GetResourceString("EventSource_KeywordCollision", name, prevName, "0x" + value.ToString("x", CultureInfo.CurrentCulture)));
+                }
             }
             if (keywordTab == null)
                 keywordTab = new Dictionary<ulong, string>();
@@ -6091,13 +6114,13 @@ namespace System.Diagnostics.Tracing
         {
             EventChannel chValue = (EventChannel)value;
             if (value < (int)EventChannel.Admin || value > 255)
-                ManifestError(Environment.GetResourceString("EventSource_EventChannelOutOfRange", name, value));
+                ManifestError(Resources.GetResourceString("EventSource_EventChannelOutOfRange", name, value));
             else if (chValue >= EventChannel.Admin && chValue <= EventChannel.Debug &&
                      channelAttribute != null && EventChannelToChannelType(chValue) != channelAttribute.EventChannelType)
             {
                 // we want to ensure developers do not define EventChannels that conflict with the builtin ones,
                 // but we want to allow them to override the default ones...
-                ManifestError(Environment.GetResourceString("EventSource_ChannelTypeDoesNotMatchEventChannelValue",
+                ManifestError(Resources.GetResourceString("EventSource_ChannelTypeDoesNotMatchEventChannelValue",
                                                                             name, ((EventChannel)value).ToString()));
             }
 
@@ -6264,7 +6287,7 @@ namespace System.Diagnostics.Tracing
             }
 
             if (channelTab.Count == MaxCountChannels)
-                ManifestError(Environment.GetResourceString("EventSource_MaxChannelExceeded"));
+                ManifestError(Resources.GetResourceString("EventSource_MaxChannelExceeded"));
 
             ulong channelKeyword;
             ChannelInfo info;
@@ -6489,7 +6512,7 @@ namespace System.Diagnostics.Tracing
                 cultures = new List<CultureInfo>();
                 cultures.Add(CultureInfo.CurrentUICulture);
             }
-#if ES_BUILD_STANDALONE
+#if ES_BUILD_STANDALONE || PROJECTN
             var sortedStrings = new List<string>(stringTab.Keys);
             sortedStrings.Sort();
 #else
@@ -6544,7 +6567,7 @@ namespace System.Diagnostics.Tracing
             string prevValue;
             if (stringTab.TryGetValue(key, out prevValue) && !prevValue.Equals(value))
             {
-                ManifestError(Environment.GetResourceString("EventSource_DuplicateStringKey", key), true);
+                ManifestError(Resources.GetResourceString("EventSource_DuplicateStringKey", key), true);
                 return;
             }
 
@@ -6582,7 +6605,7 @@ namespace System.Diagnostics.Tracing
         private static List<CultureInfo> GetSupportedCultures(ResourceManager resources)
         {
             var cultures = new List<CultureInfo>();
-#if !ES_BUILD_PCL && !FEATURE_CORECLR
+#if !ES_BUILD_PCL && !FEATURE_CORECLR && !PROJECTN
             foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.SpecificCultures /*| CultureTypes.NeutralCultures*/))
             {
                 if (resources.GetResourceSet(ci, true, false) != null)
@@ -6606,26 +6629,26 @@ namespace System.Diagnostics.Tracing
             if (channelTab == null || !channelTab.TryGetValue((int)channel, out info))
             {
                 if (channel < EventChannel.Admin) // || channel > EventChannel.Debug)
-                    ManifestError(Environment.GetResourceString("EventSource_UndefinedChannel", channel, eventName));
+                    ManifestError(Resources.GetResourceString("EventSource_UndefinedChannel", channel, eventName));
 
                 // allow channels to be auto-defined.  The well known ones get their well known names, and the
                 // rest get names Channel<N>.  This allows users to modify the Manifest if they want more advanced features. 
                 if (channelTab == null)
                     channelTab = new Dictionary<int, ChannelInfo>(4);
-                
+
                 string channelName = channel.ToString();        // For well know channels this is a nice name, otherwise a number 
                 if (EventChannel.Debug < channel)
                     channelName = "Channel" + channelName;      // Add a 'Channel' prefix for numbers.  
 
                 AddChannel(channelName, (int)channel, GetDefaultChannelAttribute(channel));
                 if (!channelTab.TryGetValue((int)channel, out info))
-                    ManifestError(Environment.GetResourceString("EventSource_UndefinedChannel", channel, eventName));
+                    ManifestError(Resources.GetResourceString("EventSource_UndefinedChannel", channel, eventName));
             }
             // events that specify admin channels *must* have non-null "Message" attributes
             if (resources != null && eventMessage == null)
                 eventMessage = resources.GetString("event_" + eventName, CultureInfo.InvariantCulture);
             if (info.Attribs.EventChannelType == EventChannelType.Admin && eventMessage == null)
-                ManifestError(Environment.GetResourceString("EventSource_EventWithAdminChannelMustHaveMessage", eventName, info.Name));
+                ManifestError(Resources.GetResourceString("EventSource_EventWithAdminChannelMustHaveMessage", eventName, info.Name));
             return info.Name;
         }
 #endif
@@ -6641,6 +6664,7 @@ namespace System.Diagnostics.Tracing
                 ret = taskTab[(int)task] = eventName;
             return ret;
         }
+        
         private string GetOpcodeName(EventOpcode opcode, string eventName)
         {
             switch (opcode)
@@ -6672,11 +6696,12 @@ namespace System.Diagnostics.Tracing
             string ret;
             if (opcodeTab == null || !opcodeTab.TryGetValue((int)opcode, out ret))
             {
-                ManifestError(Environment.GetResourceString("EventSource_UndefinedOpcode", opcode, eventName), true);
+                ManifestError(Resources.GetResourceString("EventSource_UndefinedOpcode", opcode, eventName), true);
                 ret = null;
             }
             return ret;
         }
+        
         private string GetKeywords(ulong keywords, string eventName)
         {
             string ret = "";
@@ -6694,7 +6719,7 @@ namespace System.Diagnostics.Tracing
                     }
                     if (keyword == null)
                     {
-                        ManifestError(Environment.GetResourceString("EventSource_UndefinedKeyword", "0x" + bit.ToString("x", CultureInfo.CurrentCulture), eventName), true);
+                        ManifestError(Resources.GetResourceString("EventSource_UndefinedKeyword", "0x" + bit.ToString("x", CultureInfo.CurrentCulture), eventName), true);
                         keyword = string.Empty;
                     }
                     if (ret.Length != 0 && keyword.Length != 0)
@@ -6704,6 +6729,7 @@ namespace System.Diagnostics.Tracing
             }
             return ret;
         }
+        
         private string GetTypeName(Type type)
         {
             if (type.IsEnum())
@@ -6712,45 +6738,8 @@ namespace System.Diagnostics.Tracing
                 var typeName = GetTypeName(fields[0].FieldType);
                 return typeName.Replace("win:Int", "win:UInt"); // ETW requires enums to be unsigned.  
             }
-            switch (type.GetTypeCode())
-            {
-                case TypeCode.Boolean:
-                    return "win:Boolean";
-                case TypeCode.Byte:
-                    return "win:UInt8";
-                case TypeCode.Char:
-                case TypeCode.UInt16:
-                    return "win:UInt16";
-                case TypeCode.UInt32:
-                    return "win:UInt32";
-                case TypeCode.UInt64:
-                    return "win:UInt64";
-                case TypeCode.SByte:
-                    return "win:Int8";
-                case TypeCode.Int16:
-                    return "win:Int16";
-                case TypeCode.Int32:
-                    return "win:Int32";
-                case TypeCode.Int64:
-                    return "win:Int64";
-                case TypeCode.String:
-                    return "win:UnicodeString";
-                case TypeCode.Single:
-                    return "win:Float";
-                case TypeCode.Double:
-                    return "win:Double";
-                case TypeCode.DateTime:
-                    return "win:FILETIME";
-                default:
-                    if (type == typeof(Guid))
-                        return "win:GUID";
-                    else if (type == typeof(IntPtr))
-                        return "win:Pointer";
-                    else if ((type.IsArray || type.IsPointer) && type.GetElementType() == typeof(byte))
-                        return "win:Binary";
-                    ManifestError(Environment.GetResourceString("EventSource_UnsupportedEventTypeInManifest", type.Name), true);
-                    return string.Empty;
-            }
+            
+            return GetTypeNameHelper(type);
         }
 
         private static void UpdateStringBuilder(ref StringBuilder stringBuilder, string eventMessage, int startIndex, int count)
@@ -6822,7 +6811,7 @@ namespace System.Diagnostics.Tracing
                     }
                     else
                     {
-                        ManifestError(Environment.GetResourceString("EventSource_UnsupportedMessageProperty", evtName, eventMessage));
+                        ManifestError(Resources.GetResourceString("EventSource_UnsupportedMessageProperty", evtName, eventMessage));
                     }
                 }
                 else if ((chIdx = "&<>'\"\r\n\t".IndexOf(eventMessage[i])) >= 0)
index f950c6f..4e11c80 100644 (file)
@@ -17,7 +17,7 @@ namespace System.Diagnostics.Tracing
     /// <summary>
     /// Exception that is thrown when an error occurs during EventSource operation.
     /// </summary>
-#if !ES_BUILD_PCL
+#if (!ES_BUILD_PCL && !PROJECTN)
     [Serializable]
 #endif
     public class EventSourceException : Exception
@@ -25,7 +25,8 @@ namespace System.Diagnostics.Tracing
         /// <summary>
         /// Initializes a new instance of the EventSourceException class.
         /// </summary>
-        public EventSourceException() : base(Environment.GetResourceString("EventSource_ListenerWriteFailure")) { }
+        public EventSourceException() :
+            base(Resources.GetResourceString("EventSource_ListenerWriteFailure")) { }
 
         /// <summary>
         /// Initializes a new instance of the EventSourceException class with a specified error message.
@@ -38,13 +39,14 @@ namespace System.Diagnostics.Tracing
         /// </summary>
         public EventSourceException(string message, Exception innerException) : base(message, innerException) { }
 
-#if !ES_BUILD_PCL
+#if (!ES_BUILD_PCL && !PROJECTN)
         /// <summary>
         /// Initializes a new instance of the EventSourceException class with serialized data.
         /// </summary>
         protected EventSourceException(SerializationInfo info, StreamingContext context) : base(info, context) { }
 #endif
 
-        internal EventSourceException(Exception innerException) : base(Environment.GetResourceString("EventSource_ListenerWriteFailure"), innerException) { }
+        internal EventSourceException(Exception innerException) :
+            base(Resources.GetResourceString("EventSource_ListenerWriteFailure"), innerException) { }
     }
 }
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs b/src/mscorlib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs
new file mode 100644 (file)
index 0000000..43c8752
--- /dev/null
@@ -0,0 +1,223 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+using Microsoft.Reflection;
+using Microsoft.Win32;
+
+namespace System.Diagnostics.Tracing
+{
+    public partial class EventSource
+    {
+        // ActivityID support (see also WriteEventWithRelatedActivityIdCore)
+        /// <summary>
+        /// When a thread starts work that is on behalf of 'something else' (typically another 
+        /// thread or network request) it should mark the thread as working on that other work.
+        /// This API marks the current thread as working on activity 'activityID'. This API
+        /// should be used when the caller knows the thread's current activity (the one being
+        /// overwritten) has completed. Otherwise, callers should prefer the overload that
+        /// return the oldActivityThatWillContinue (below).
+        /// 
+        /// All events created with the EventSource on this thread are also tagged with the 
+        /// activity ID of the thread. 
+        /// 
+        /// It is common, and good practice after setting the thread to an activity to log an event
+        /// with a 'start' opcode to indicate that precise time/thread where the new activity 
+        /// started.
+        /// </summary>
+        /// <param name="activityId">A Guid that represents the new activity with which to mark 
+        /// the current thread</param>
+        [System.Security.SecuritySafeCritical]
+        public static void SetCurrentThreadActivityId(Guid activityId)
+        {
+            if (TplEtwProvider.Log != null)
+                TplEtwProvider.Log.SetActivityId(activityId);
+#if FEATURE_MANAGED_ETW
+#if FEATURE_ACTIVITYSAMPLING
+            Guid newId = activityId;
+#endif // FEATURE_ACTIVITYSAMPLING
+            // We ignore errors to keep with the convention that EventSources do not throw errors.
+            // Note we can't access m_throwOnWrites because this is a static method.  
+
+            if (UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
+                UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
+                ref activityId) == 0)
+            {
+#if FEATURE_ACTIVITYSAMPLING
+                var activityDying = s_activityDying;
+                if (activityDying != null && newId != activityId)
+                {
+                    if (activityId == Guid.Empty)
+                    {
+                        activityId = FallbackActivityId;
+                    }
+                    // OutputDebugString(string.Format("Activity dying: {0} -> {1}", activityId, newId));
+                    activityDying(activityId);     // This is actually the OLD activity ID.  
+                }
+#endif // FEATURE_ACTIVITYSAMPLING
+            }
+#endif // FEATURE_MANAGED_ETW
+        }
+
+        /// <summary>
+        /// When a thread starts work that is on behalf of 'something else' (typically another 
+        /// thread or network request) it should mark the thread as working on that other work.
+        /// This API marks the current thread as working on activity 'activityID'. It returns 
+        /// whatever activity the thread was previously marked with. There is a convention that
+        /// callers can assume that callees restore this activity mark before the callee returns. 
+        /// To encourage this this API returns the old activity, so that it can be restored later.
+        /// 
+        /// All events created with the EventSource on this thread are also tagged with the 
+        /// activity ID of the thread. 
+        /// 
+        /// It is common, and good practice after setting the thread to an activity to log an event
+        /// with a 'start' opcode to indicate that precise time/thread where the new activity 
+        /// started.
+        /// </summary>
+        /// <param name="activityId">A Guid that represents the new activity with which to mark 
+        /// the current thread</param>
+        /// <param name="oldActivityThatWillContinue">The Guid that represents the current activity  
+        /// which will continue at some point in the future, on the current thread</param>
+        [System.Security.SecuritySafeCritical]
+        public static void SetCurrentThreadActivityId(Guid activityId, out Guid oldActivityThatWillContinue)
+        {
+            oldActivityThatWillContinue = activityId;
+#if FEATURE_MANAGED_ETW
+            // We ignore errors to keep with the convention that EventSources do not throw errors.
+            // Note we can't access m_throwOnWrites because this is a static method.  
+
+            UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
+                UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
+                    ref oldActivityThatWillContinue);
+#endif // FEATURE_MANAGED_ETW
+
+            // We don't call the activityDying callback here because the caller has declared that
+            // it is not dying.  
+            if (TplEtwProvider.Log != null)
+                TplEtwProvider.Log.SetActivityId(activityId);
+        }
+
+        /// <summary>
+        /// Retrieves the ETW activity ID associated with the current thread.
+        /// </summary>
+        public static Guid CurrentThreadActivityId
+        {
+            [System.Security.SecuritySafeCritical]
+            get
+            {
+                // We ignore errors to keep with the convention that EventSources do not throw 
+                // errors. Note we can't access m_throwOnWrites because this is a static method.
+                Guid retVal = new Guid();
+#if FEATURE_MANAGED_ETW
+                UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
+                    UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID,
+                    ref retVal);
+#endif // FEATURE_MANAGED_ETW
+                return retVal;
+            }
+        }
+
+        private int GetParameterCount(EventMetadata eventData)
+        {
+            return eventData.Parameters.Length;
+        }
+
+        private Type GetDataType(EventMetadata eventData, int parameterId)
+        {
+            return eventData.Parameters[parameterId].ParameterType;
+        }
+
+        private static string GetResourceString(string key, params object[] args)
+        {
+            return Environment.GetResourceString(key, args);
+        }
+        
+        private static readonly bool m_EventSourcePreventRecursion = false;
+    }
+    
+    internal partial class ManifestBuilder
+    {
+        private string GetTypeNameHelper(Type type)
+        {
+            switch (type.GetTypeCode())
+            {
+                case TypeCode.Boolean:
+                    return "win:Boolean";
+                case TypeCode.Byte:
+                    return "win:UInt8";
+                case TypeCode.Char:
+                case TypeCode.UInt16:
+                    return "win:UInt16";
+                case TypeCode.UInt32:
+                    return "win:UInt32";
+                case TypeCode.UInt64:
+                    return "win:UInt64";
+                case TypeCode.SByte:
+                    return "win:Int8";
+                case TypeCode.Int16:
+                    return "win:Int16";
+                case TypeCode.Int32:
+                    return "win:Int32";
+                case TypeCode.Int64:
+                    return "win:Int64";
+                case TypeCode.String:
+                    return "win:UnicodeString";
+                case TypeCode.Single:
+                    return "win:Float";
+                case TypeCode.Double:
+                    return "win:Double";
+                case TypeCode.DateTime:
+                    return "win:FILETIME";
+                default:
+                    if (type == typeof(Guid))
+                        return "win:GUID";
+                    else if (type == typeof(IntPtr))
+                        return "win:Pointer";
+                    else if ((type.IsArray || type.IsPointer) && type.GetElementType() == typeof(byte))
+                        return "win:Binary";
+                        
+                    ManifestError(Environment.GetResourceString("EventSource_UnsupportedEventTypeInManifest", type.Name), true);
+                    return string.Empty;
+            }
+        }
+    }
+        
+    internal partial class EventProvider
+    {
+        [System.Security.SecurityCritical]
+        internal unsafe int SetInformation(
+            UnsafeNativeMethods.ManifestEtw.EVENT_INFO_CLASS eventInfoClass,
+            IntPtr data,
+            uint dataSize)
+        {
+            int status = UnsafeNativeMethods.ManifestEtw.ERROR_NOT_SUPPORTED;
+
+            if (!m_setInformationMissing)
+            {
+                try
+                {
+                    status = UnsafeNativeMethods.ManifestEtw.EventSetInformation(
+                        m_regHandle,
+                        eventInfoClass,
+                        (void *)data,
+                        (int)dataSize);
+                }
+                catch (TypeLoadException)
+                {
+                    m_setInformationMissing = true;
+                }
+            }
+
+            return status;
+        }
+    }
+    
+    internal static class Resources
+    {
+        internal static string GetResourceString(string key, params object[] args)
+        {
+            return Environment.GetResourceString(key, args);
+        }
+    }
+}
index a6d1050..4768baa 100644 (file)
@@ -36,7 +36,7 @@ namespace System.Diagnostics.Tracing.Internal
                     sargs += ", ";
                 sargs += arg.ToString();
             }
-          
+
             return key + " (" + sargs + ")";
         }
 
@@ -163,7 +163,7 @@ namespace Microsoft.Reflection
 {
     using System.Reflection;
 
-#if ES_BUILD_PCL
+#if (ES_BUILD_PCL || PROJECTN)
     [Flags]
     public enum BindingFlags
     {
@@ -197,14 +197,16 @@ namespace Microsoft.Reflection
 #endif
     static class ReflectionExtensions
     {
-#if !ES_BUILD_PCL
-        
+#if (!ES_BUILD_PCL && !PROJECTN)
+
         //
         // Type extension methods
         //
         public static bool IsEnum(this Type type) { return type.IsEnum; }
         public static bool IsAbstract(this Type type) { return type.IsAbstract; }
         public static bool IsSealed(this Type type) { return type.IsSealed; }
+        public static bool IsValueType(this Type type) { return type.IsValueType; }
+        public static bool IsGenericType(this Type type) { return type.IsGenericType; }
         public static Type BaseType(this Type type) { return type.BaseType; }
         public static Assembly Assembly(this Type type) { return type.Assembly; }
         public static TypeCode GetTypeCode(this Type type) { return Type.GetTypeCode(type); }
@@ -219,9 +221,14 @@ namespace Microsoft.Reflection
         public static bool IsEnum(this Type type) { return type.GetTypeInfo().IsEnum; }
         public static bool IsAbstract(this Type type) { return type.GetTypeInfo().IsAbstract; }
         public static bool IsSealed(this Type type) { return type.GetTypeInfo().IsSealed; }
+        public static bool IsValueType(this Type type) { return type.GetTypeInfo().IsValueType; }
+        public static bool IsGenericType(this Type type) { return type.IsConstructedGenericType; }
         public static Type BaseType(this Type type) { return type.GetTypeInfo().BaseType; }
         public static Assembly Assembly(this Type type) { return type.GetTypeInfo().Assembly; }
-
+        public static IEnumerable<PropertyInfo> GetProperties(this Type type) { return type.GetTypeInfo().DeclaredProperties; }
+        public static MethodInfo GetGetMethod(this PropertyInfo propInfo) { return propInfo.GetMethod; }
+        public static Type[] GetGenericArguments(this Type type) { return type.GenericTypeArguments; }
+        
         public static MethodInfo[] GetMethods(this Type type, BindingFlags flags)
         {
             // Minimal implementation to cover only the cases we need
@@ -333,7 +340,7 @@ namespace Microsoft.Reflection
 }
 
 // Defining some no-ops in PCL builds
-#if ES_BUILD_PCL
+#if ES_BUILD_PCL || PROJECTN
 namespace System.Security
 {
     class SuppressUnmanagedCodeSecurityAttribute : Attribute { }
@@ -349,4 +356,17 @@ namespace System.Security.Permissions
         public bool Unrestricted { get; set; }
     }
 }
-#endif
\ No newline at end of file
+#endif
+
+#if PROJECTN
+namespace System
+{
+    public static class AppDomain
+    {
+        public static int GetCurrentThreadId()
+        {
+            return (int)Interop.mincore.GetCurrentThreadId();
+        }
+    }    
+}
+#endif
index ce98e38..88d04e3 100644 (file)
@@ -10,12 +10,12 @@ namespace Microsoft.Diagnostics.Tracing
 namespace System.Diagnostics.Tracing
 #endif
 {
-    internal sealed class ArrayTypeInfo<ElementType>
-        : TraceLoggingTypeInfo<ElementType[]>
+    internal sealed class ArrayTypeInfo : TraceLoggingTypeInfo
     {
-        private readonly TraceLoggingTypeInfo<ElementType> elementInfo;
+        private readonly TraceLoggingTypeInfo elementInfo;
 
-        public ArrayTypeInfo(TraceLoggingTypeInfo<ElementType> elementInfo)
+        public ArrayTypeInfo(Type type, TraceLoggingTypeInfo elementInfo)
+            : base(type)
         {
             this.elementInfo = elementInfo;
         }
@@ -30,19 +30,18 @@ namespace System.Diagnostics.Tracing
             collector.EndBufferedArray();
         }
 
-        public override void WriteData(
-            TraceLoggingDataCollector collector,
-            ref ElementType[] value)
+        public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
         {
             var bookmark = collector.BeginBufferedArray();
 
             var count = 0;
-            if (value != null)
+            Array array = (Array)value.ReferenceValue;
+            if (array != null)
             {
-                count = value.Length;
-                for (int i = 0; i < value.Length; i++)
+                count = array.Length;
+                for (int i = 0; i < array.Length; i++)
                 {
-                    this.elementInfo.WriteData(collector, ref value[i]);
+                    this.elementInfo.WriteData(collector, elementInfo.PropertyValueFactory(array.GetValue(i)));
                 }
             }
 
@@ -51,11 +50,11 @@ namespace System.Diagnostics.Tracing
 
         public override object GetData(object value)
         {
-            var array = (ElementType[])value;
+            var array = (Array)value;
             var serializedArray = new object[array.Length];
             for (int i = 0; i < array.Length; i++)
             {
-                serializedArray[i] = this.elementInfo.GetData(array[i]);
+                serializedArray[i] = this.elementInfo.GetData(array.GetValue(i));
             }
             return serializedArray;
         }
index 238a0d8..1cbc942 100644 (file)
@@ -85,7 +85,7 @@ namespace System.Diagnostics.Tracing
                 var scratchNew = scratchOld + size;
                 if (this.scratchEnd < scratchNew)
                 {
-                    throw new IndexOutOfRangeException(Environment.GetResourceString("EventSource_AddScalarOutOfRange"));
+                    throw new IndexOutOfRangeException(Resources.GetResourceString("EventSource_AddScalarOutOfRange"));
                 }
 
                 this.ScalarsBegin();
@@ -272,13 +272,13 @@ namespace System.Diagnostics.Tracing
             var pinsTemp = this.pins;
             if (this.pinsEnd <= pinsTemp)
             {
-                throw new IndexOutOfRangeException(Environment.GetResourceString("EventSource_PinArrayOutOfRange"));
+                throw new IndexOutOfRangeException(Resources.GetResourceString("EventSource_PinArrayOutOfRange"));
             }
 
             var datasTemp = this.datas;
             if (this.datasEnd <= datasTemp)
             {
-                throw new IndexOutOfRangeException(Environment.GetResourceString("EventSource_DataDescriptorsOutOfRange"));
+                throw new IndexOutOfRangeException(Resources.GetResourceString("EventSource_DataDescriptorsOutOfRange"));
             }
 
             this.pins = pinsTemp + 1;
@@ -296,7 +296,7 @@ namespace System.Diagnostics.Tracing
                 var datasTemp = this.datas;
                 if (this.datasEnd <= datasTemp)
                 {
-                    throw new IndexOutOfRangeException(Environment.GetResourceString("EventSource_DataDescriptorsOutOfRange"));
+                    throw new IndexOutOfRangeException(Resources.GetResourceString("EventSource_DataDescriptorsOutOfRange"));
                 }
 
                 datasTemp->m_Ptr = (long)(ulong)(UIntPtr)this.scratch;
index 12e0584..095a0cd 100644 (file)
@@ -1,7 +1,7 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
+#if EVENTSOURCE_GENERICS
+?using System;
 using System.Reflection;
 
 #if ES_BUILD_STANDALONE
@@ -19,27 +19,11 @@ namespace System.Diagnostics.Tracing
     /// </typeparam>
     internal static class EnumHelper<UnderlyingType>
     {
-        private delegate UnderlyingType Transformer<ValueType>(ValueType value);
-
-        private static readonly MethodInfo IdentityInfo =
-            Statics.GetDeclaredStaticMethod(typeof(EnumHelper<UnderlyingType>), "Identity");
-
         public static UnderlyingType Cast<ValueType>(ValueType value)
         {
-            return Caster<ValueType>.Instance(value);
-        }
-
-        internal static UnderlyingType Identity(UnderlyingType value)
-        {
-            return value;
-        }
-
-        private static class Caster<ValueType>
-        {
-            public static readonly Transformer<ValueType> Instance =
-                (Transformer<ValueType>)Statics.CreateDelegate(
-                typeof(Transformer<ValueType>),
-                IdentityInfo);
+            return (UnderlyingType)(object)value;
         }
     }
+
 }
+#endif
index af5e60b..8f3605e 100644 (file)
@@ -2,6 +2,7 @@
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
 using System;
+using System.Collections;
 using System.Collections.Generic;
 
 #if ES_BUILD_STANDALONE
@@ -10,13 +11,12 @@ namespace Microsoft.Diagnostics.Tracing
 namespace System.Diagnostics.Tracing
 #endif
 {
-    internal sealed class EnumerableTypeInfo<IterableType, ElementType>
-        : TraceLoggingTypeInfo<IterableType>
-        where IterableType : IEnumerable<ElementType>
+    internal sealed class EnumerableTypeInfo : TraceLoggingTypeInfo
     {
-        private readonly TraceLoggingTypeInfo<ElementType> elementInfo;
+        private readonly TraceLoggingTypeInfo elementInfo;
 
-        public EnumerableTypeInfo(TraceLoggingTypeInfo<ElementType> elementInfo)
+        public EnumerableTypeInfo(Type type, TraceLoggingTypeInfo elementInfo)
+            : base(type)
         {
             this.elementInfo = elementInfo;
         }
@@ -31,19 +31,17 @@ namespace System.Diagnostics.Tracing
             collector.EndBufferedArray();
         }
 
-        public override void WriteData(
-            TraceLoggingDataCollector collector,
-            ref IterableType value)
+        public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
         {
             var bookmark = collector.BeginBufferedArray();
 
             var count = 0;
-            if (value != null)
+            IEnumerable enumerable = (IEnumerable)value.ReferenceValue;
+            if (enumerable != null)
             {
-                foreach (var element in value)
+                foreach (var element in enumerable)
                 {
-                    var el = element;
-                    this.elementInfo.WriteData(collector, ref el);
+                    this.elementInfo.WriteData(collector, elementInfo.PropertyValueFactory(element));
                     count++;
                 }
             }
@@ -53,7 +51,7 @@ namespace System.Diagnostics.Tracing
 
         public override object GetData(object value)
         {
-            var iterType = (IterableType)value;
+            var iterType = (IEnumerable)value;
             List<object> serializedEnumerable = new List<object>();
             foreach (var element in iterType)
             {
index 4095352..7e6ed76 100644 (file)
@@ -24,7 +24,7 @@ namespace System.Diagnostics.Tracing
         /// Field should not be displayed.
         /// </summary>
         NoPrint = 1,
-#endif 
+#endif
         /// <summary>
         /// Field should be formatted as character or string data.
         /// Typically applied to 8-bit or 16-bit integers.
@@ -77,7 +77,7 @@ namespace System.Diagnostics.Tracing
         /// Field should be formatted as a SOCKADDR. Typically applied to byte[] types.
         /// </summary>
         SocketAddress = 10,
-#endif 
+#endif
         /// <summary>
         /// Field should be formatted as XML string data. Typically applied to
         /// strings or arrays of 8-bit or 16-bit integers.
index 3279a76..dcaa9fd 100644 (file)
@@ -256,7 +256,7 @@ namespace System.Diagnostics.Tracing
                 newActivity.startStopOptions.Opcode = EventOpcode.Start;
                 this.eventSource.Write(eventName, ref newActivity.startStopOptions, ref newActivity.activityId, ref relatedActivityId, ref data);
             }
-            else 
+            else
             {
                 // If we are not active, we don't set the eventName, which basically also turns off the Stop event as well.  
                 newActivity.activityId = this.Id;
@@ -305,11 +305,11 @@ namespace System.Diagnostics.Tracing
         /// <summary>
         /// If eventName is non-null then we logged a start event 
         /// </summary>
-        private bool StartEventWasFired { get { return eventName != null; }}
+        private bool StartEventWasFired { get { return eventName != null; } }
 
         private readonly EventSource eventSource;
         private EventSourceOptions startStopOptions;
-        internal  Guid activityId;
+        internal Guid activityId;
         // internal Guid relatedActivityId;
         private State state;
         private string eventName;
index b64940a..404b0a7 100644 (file)
@@ -127,17 +127,17 @@ namespace System.Diagnostics.Tracing
             {
                 if (coreType == (int)TraceLoggingDataType.Nil)
                 {
-                    throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedArrayOfNil"));
+                    throw new NotSupportedException(Resources.GetResourceString("EventSource_NotSupportedArrayOfNil"));
                 }
                 if (coreType == (int)TraceLoggingDataType.Binary)
                 {
-                    throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedArrayOfBinary"));
+                    throw new NotSupportedException(Resources.GetResourceString("EventSource_NotSupportedArrayOfBinary"));
                 }
 #if !BROKEN_UNTIL_M3
                 if (coreType == (int)TraceLoggingDataType.Utf16String ||
                     coreType == (int)TraceLoggingDataType.MbcsString)
                 {
-                    throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedArrayOfNullTerminatedString"));
+                    throw new NotSupportedException(Resources.GetResourceString("EventSource_NotSupportedArrayOfNullTerminatedString"));
                 }
 #endif
             }
@@ -159,7 +159,7 @@ namespace System.Diagnostics.Tracing
             this.outType++;
             if ((this.outType & Statics.OutTypeMask) == 0)
             {
-                throw new NotSupportedException(Environment.GetResourceString("EventSource_TooManyFields"));
+                throw new NotSupportedException(Resources.GetResourceString("EventSource_TooManyFields"));
             }
         }
 
index 903114f..653f605 100644 (file)
@@ -13,20 +13,20 @@ namespace System.Diagnostics.Tracing
     /// <summary>
     /// TraceLogging: An implementation of TraceLoggingTypeInfo that works
     /// for arbitrary types. It writes all public instance properties of
-    /// the type. Implemented using Delegate.CreateDelegate(property.Getter).
+    /// the type.
     /// </summary>
     /// <typeparam name="ContainerType">
     /// Type from which to read values.
     /// </typeparam>
-    internal sealed class InvokeTypeInfo<ContainerType>
-        : TraceLoggingTypeInfo<ContainerType>
+    internal sealed class InvokeTypeInfo : TraceLoggingTypeInfo
     {
         private readonly PropertyAnalysis[] properties;
-        private readonly PropertyAccessor<ContainerType>[] accessors;
 
         public InvokeTypeInfo(
+            Type type,
             TypeAnalysis typeAnalysis)
             : base(
+                type,
                 typeAnalysis.name,
                 typeAnalysis.level,
                 typeAnalysis.opcode,
@@ -34,14 +34,7 @@ namespace System.Diagnostics.Tracing
                 typeAnalysis.tags)
         {
             if (typeAnalysis.properties.Length != 0)
-            {
                 this.properties = typeAnalysis.properties;
-                this.accessors = new PropertyAccessor<ContainerType>[this.properties.Length];
-                for (int i = 0; i < this.accessors.Length; i++)
-                {
-                    this.accessors[i] = PropertyAccessor<ContainerType>.Create(this.properties[i]);
-                }
-            }
         }
 
         public override void WriteMetadata(
@@ -70,15 +63,13 @@ namespace System.Diagnostics.Tracing
             }
         }
 
-        public override void WriteData(
-            TraceLoggingDataCollector collector,
-            ref ContainerType value)
+        public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
         {
-            if (this.accessors != null)
+            if (this.properties != null)
             {
-                foreach (var accessor in this.accessors)
+                foreach (var property in this.properties)
                 {
-                    accessor.Write(collector, ref value);
+                    property.typeInfo.WriteData(collector, property.getter(value));
                 }
             }
         }
@@ -91,7 +82,7 @@ namespace System.Diagnostics.Tracing
                 var memebersValues = new List<object>();
                 for (int i = 0; i < this.properties.Length; i++)
                 {
-                    var propertyValue = accessors[i].GetData((ContainerType)value);
+                    var propertyValue = properties[i].propertyInfo.GetValue(value);
                     membersNames.Add(properties[i].name);
                     memebersValues.Add(properties[i].typeInfo.GetData(propertyValue));
                 }
@@ -100,18 +91,5 @@ namespace System.Diagnostics.Tracing
 
             return null;
         }
-
-        public override void WriteObjectData(
-            TraceLoggingDataCollector collector,
-            object valueObj)
-        {
-            if (this.accessors != null)
-            {
-                var value = valueObj == null
-                    ? default(ContainerType)
-                    : (ContainerType)valueObj;
-                this.WriteData(collector, ref value);
-            }
-        }
     }
 }
index acc7607..1a428e5 100644 (file)
@@ -26,14 +26,14 @@ namespace System.Diagnostics.Tracing
         {
             for(;;)
             {
-                int snapshot =lastIdentity;
+                int snapshot = lastIdentity;
                 int newIdentity = (lastIdentity & ~0xFFFFFF) + eventId;
                 newIdentity = Math.Max(newIdentity, snapshot);      // Should be redundant.  as we only create descriptors once.  
                 if (Interlocked.CompareExchange(ref lastIdentity, newIdentity, snapshot) == snapshot)
                     break;
             }
         }
+
         private static int lastIdentity = Statics.TraceLoggingChannel << 24;
         internal readonly string name;
         internal readonly EventTags tags;
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyAccessor.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyAccessor.cs
deleted file mode 100644 (file)
index 388e0b6..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Reflection;
-
-#if ES_BUILD_STANDALONE
-namespace Microsoft.Diagnostics.Tracing
-#else
-namespace System.Diagnostics.Tracing
-#endif
-{
-    /// <summary>
-    /// TraceLogging: Each PropertyAccessor instance encapsulates the information
-    /// needed to read a particular property from an instance of ContainerType
-    /// and write the value to a DataCollector. Used by InvokeTypeInfo.
-    /// </summary>
-    /// <typeparam name="ContainerType">
-    /// The type of the object from which properties are read.
-    /// </typeparam>
-    internal abstract class PropertyAccessor<ContainerType>
-    {
-        public abstract void Write(TraceLoggingDataCollector collector, ref ContainerType value);
-        public abstract object GetData(ContainerType value);
-
-        public static PropertyAccessor<ContainerType> Create(PropertyAnalysis property)
-        {
-            // Due to current Project N limitations on handling generic instantiations with
-            // 2 generic parameters we have to explicitly create the instantiations that we consider 
-            // important to EventSource performance (we have considered int, long, string for the moment). 
-            // Everything else is handled by NonGenericPropertyWriter that ends up boxing the container object. 
-            var retType = property.getterInfo.ReturnType;
-            if (!Statics.IsValueType(typeof(ContainerType)))
-            {
-                if (retType == typeof(int))
-                    return new ClassPropertyWriter<ContainerType, int>(property);
-                else if (retType == typeof(long))
-                    return new ClassPropertyWriter<ContainerType, long>(property);
-                else if (retType == typeof(string))
-                    return new ClassPropertyWriter<ContainerType, string>(property);
-            }
-            else
-            {
-                // Handle the case if it is a struct (DD 1027919)
-            }
-
-            // Otherwise use the boxing one.  
-            return new NonGenericProperytWriter<ContainerType>(property);
-        }
-    }
-
-    /// <summary>
-    /// The type specific version of the property writers uses generics in a way 
-    /// that Project N can't handle at the moment.   To avoid this we simply 
-    /// use reflection completely.  
-    /// </summary>
-    internal class NonGenericProperytWriter<ContainerType> : PropertyAccessor<ContainerType>
-    {
-        public NonGenericProperytWriter(PropertyAnalysis property)
-        {
-            getterInfo = property.getterInfo;
-            typeInfo = property.typeInfo;
-        }
-
-        public override void Write(TraceLoggingDataCollector collector, ref ContainerType container)
-        {
-            object value = container == null
-                ? null
-                : getterInfo.Invoke((object)container, null);
-            this.typeInfo.WriteObjectData(collector, value);
-        }
-
-        public override object GetData(ContainerType container)
-        {
-            return container == null
-                ? default(ValueType)
-                : getterInfo.Invoke((object)container, null);
-        }
-
-        private readonly TraceLoggingTypeInfo typeInfo;
-        private readonly MethodInfo getterInfo;
-    }
-
-    /// <summary>
-    /// Implementation of PropertyAccessor for use when ContainerType is a
-    /// value type.
-    /// </summary>
-    /// <typeparam name="ContainerType">The type of the object from which properties are read.</typeparam>
-    /// <typeparam name="ValueType">Type of the property being read.</typeparam>
-    internal class StructPropertyWriter<ContainerType, ValueType>
-            : PropertyAccessor<ContainerType>
-    {
-        private delegate ValueType Getter(ref ContainerType container);
-        private readonly TraceLoggingTypeInfo<ValueType> valueTypeInfo;
-        private readonly Getter getter;
-
-        public StructPropertyWriter(PropertyAnalysis property)
-        {
-            this.valueTypeInfo = (TraceLoggingTypeInfo<ValueType>)property.typeInfo;
-            this.getter = (Getter)Statics.CreateDelegate(
-                typeof(Getter),
-                property.getterInfo);
-        }
-
-        public override void Write(TraceLoggingDataCollector collector, ref ContainerType container)
-        {
-            var value = container == null
-                ? default(ValueType)
-                : getter(ref container);
-            this.valueTypeInfo.WriteData(collector, ref value);
-        }
-
-        public override object GetData(ContainerType container)
-        {
-            return container == null
-                ? default(ValueType)
-                : getter(ref container);
-        }
-    }
-
-    /// <summary>
-    /// Implementation of PropertyAccessor for use when ContainerType is a
-    /// reference type.
-    /// </summary>
-    /// <typeparam name="ContainerType">The type of the object from which properties are read.</typeparam>
-    /// <typeparam name="ValueType">Type of the property being read.</typeparam>
-    internal class ClassPropertyWriter<ContainerType, ValueType>
-            : PropertyAccessor<ContainerType>
-    {
-        private delegate ValueType Getter(ContainerType container);
-        private readonly TraceLoggingTypeInfo<ValueType> valueTypeInfo;
-        private readonly Getter getter;
-
-        public ClassPropertyWriter(PropertyAnalysis property)
-        {
-            this.valueTypeInfo = (TraceLoggingTypeInfo<ValueType>)property.typeInfo;
-            this.getter = (Getter)Statics.CreateDelegate(
-                typeof(Getter),
-                property.getterInfo);
-        }
-
-        public override void Write(TraceLoggingDataCollector collector, ref ContainerType container)
-        {
-            var value = container == null
-                ? default(ValueType)
-                : getter(container);
-            this.valueTypeInfo.WriteData(collector, ref value);
-        }
-
-        public override object GetData(ContainerType container)
-        {
-            return container == null
-                ? default(ValueType)
-                : getter(container);
-        }
-    }
-}
index 64972d1..4688a92 100644 (file)
@@ -17,18 +17,20 @@ namespace System.Diagnostics.Tracing
     internal sealed class PropertyAnalysis
     {
         internal readonly string name;
-        internal readonly MethodInfo getterInfo;
+        internal readonly PropertyInfo propertyInfo;
+        internal readonly Func<PropertyValue, PropertyValue> getter;
         internal readonly TraceLoggingTypeInfo typeInfo;
         internal readonly EventFieldAttribute fieldAttribute;
 
         public PropertyAnalysis(
             string name,
-            MethodInfo getterInfo,
+            PropertyInfo propertyInfo,
             TraceLoggingTypeInfo typeInfo,
             EventFieldAttribute fieldAttribute)
         {
             this.name = name;
-            this.getterInfo = getterInfo;
+            this.propertyInfo = propertyInfo;
+            this.getter = PropertyValue.GetPropertyGetter(propertyInfo);
             this.typeInfo = typeInfo;
             this.fieldAttribute = fieldAttribute;
         }
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyValue.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyValue.cs
new file mode 100644 (file)
index 0000000..0f34d95
--- /dev/null
@@ -0,0 +1,251 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+#if !ES_BUILD_AGAINST_DOTNET_V35
+using Contract = System.Diagnostics.Contracts.Contract;
+#else
+using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
+#endif
+
+namespace System.Diagnostics.Tracing
+{
+    /// <summary>
+    /// Holds property values of any type.  For common value types, we have inline storage so that we don't need
+    /// to box the values.  For all other types, we store the value in a single object reference field.
+    /// 
+    /// To get the value of a property quickly, use a delegate produced by <see cref="PropertyValue.GetPropertyGetter(PropertyInfo)"/>.
+    /// </summary>
+    internal unsafe struct PropertyValue
+    {
+        /// <summary>
+        /// Union of well-known value types, to avoid boxing those types.
+        /// </summary>
+        [StructLayout(LayoutKind.Explicit)]
+        public struct Scalar
+        {
+            [FieldOffset(0)]
+            public Boolean AsBoolean;
+            [FieldOffset(0)]
+            public Byte AsByte;
+            [FieldOffset(0)]
+            public SByte AsSByte;
+            [FieldOffset(0)]
+            public Char AsChar;
+            [FieldOffset(0)]
+            public Int16 AsInt16;
+            [FieldOffset(0)]
+            public UInt16 AsUInt16;
+            [FieldOffset(0)]
+            public Int32 AsInt32;
+            [FieldOffset(0)]
+            public UInt32 AsUInt32;
+            [FieldOffset(0)]
+            public Int64 AsInt64;
+            [FieldOffset(0)]
+            public UInt64 AsUInt64;
+            [FieldOffset(0)]
+            public IntPtr AsIntPtr;
+            [FieldOffset(0)]
+            public UIntPtr AsUIntPtr;
+            [FieldOffset(0)]
+            public Single AsSingle;
+            [FieldOffset(0)]
+            public Double AsDouble;
+            [FieldOffset(0)]
+            public Guid AsGuid;
+            [FieldOffset(0)]
+            public DateTime AsDateTime;
+            [FieldOffset(0)]
+            public DateTimeOffset AsDateTimeOffset;
+            [FieldOffset(0)]
+            public TimeSpan AsTimeSpan;
+            [FieldOffset(0)]
+            public Decimal AsDecimal;
+        }
+
+        // Anything not covered by the Scalar union gets stored in this reference.
+        readonly object _reference;
+        readonly Scalar _scalar;
+        readonly int _scalarLength;
+
+        private PropertyValue(object value)
+        {
+            _reference = value;
+            _scalar = default(Scalar);
+            _scalarLength = 0;
+        }
+
+        private PropertyValue(Scalar scalar, int scalarLength)
+        {
+            _reference = null;
+            _scalar = scalar;
+            _scalarLength = scalarLength;
+        }
+
+        private PropertyValue(Boolean value) : this(new Scalar() { AsBoolean = value }, sizeof(Boolean)) { }
+        private PropertyValue(Byte value) : this(new Scalar() { AsByte = value }, sizeof(Byte)) { }
+        private PropertyValue(SByte value) : this(new Scalar() { AsSByte = value }, sizeof(SByte)) { }
+        private PropertyValue(Char value) : this(new Scalar() { AsChar = value }, sizeof(Char)) { }
+        private PropertyValue(Int16 value) : this(new Scalar() { AsInt16 = value }, sizeof(Int16)) { }
+        private PropertyValue(UInt16 value) : this(new Scalar() { AsUInt16 = value }, sizeof(UInt16)) { }
+        private PropertyValue(Int32 value) : this(new Scalar() { AsInt32 = value }, sizeof(Int32)) { }
+        private PropertyValue(UInt32 value) : this(new Scalar() { AsUInt32 = value }, sizeof(UInt32)) { }
+        private PropertyValue(Int64 value) : this(new Scalar() { AsInt64 = value }, sizeof(Int64)) { }
+        private PropertyValue(UInt64 value) : this(new Scalar() { AsUInt64 = value }, sizeof(UInt64)) { }
+        private PropertyValue(IntPtr value) : this(new Scalar() { AsIntPtr = value }, sizeof(IntPtr)) { }
+        private PropertyValue(UIntPtr value) : this(new Scalar() { AsUIntPtr = value }, sizeof(UIntPtr)) { }
+        private PropertyValue(Single value) : this(new Scalar() { AsSingle = value }, sizeof(Single)) { }
+        private PropertyValue(Double value) : this(new Scalar() { AsDouble = value }, sizeof(Double)) { }
+        private PropertyValue(Guid value) : this(new Scalar() { AsGuid = value }, sizeof(Guid)) { }
+        private PropertyValue(DateTime value) : this(new Scalar() { AsDateTime = value }, sizeof(DateTime)) { }
+        private PropertyValue(DateTimeOffset value) : this(new Scalar() { AsDateTimeOffset = value }, sizeof(DateTimeOffset)) { }
+        private PropertyValue(TimeSpan value) : this(new Scalar() { AsTimeSpan = value }, sizeof(TimeSpan)) { }
+        private PropertyValue(Decimal value) : this(new Scalar() { AsDecimal = value }, sizeof(Decimal)) { }
+
+        public static Func<object, PropertyValue> GetFactory(Type type)
+        {
+            if (type == typeof(Boolean)) return value => new PropertyValue((Boolean)value);
+            if (type == typeof(Byte)) return value => new PropertyValue((Byte)value);
+            if (type == typeof(SByte)) return value => new PropertyValue((SByte)value);
+            if (type == typeof(Char)) return value => new PropertyValue((Char)value);
+            if (type == typeof(Int16)) return value => new PropertyValue((Int16)value);
+            if (type == typeof(UInt16)) return value => new PropertyValue((UInt16)value);
+            if (type == typeof(Int32)) return value => new PropertyValue((Int32)value);
+            if (type == typeof(UInt32)) return value => new PropertyValue((UInt32)value);
+            if (type == typeof(Int64)) return value => new PropertyValue((Int64)value);
+            if (type == typeof(UInt64)) return value => new PropertyValue((UInt64)value);
+            if (type == typeof(IntPtr)) return value => new PropertyValue((IntPtr)value);
+            if (type == typeof(UIntPtr)) return value => new PropertyValue((UIntPtr)value);
+            if (type == typeof(Single)) return value => new PropertyValue((Single)value);
+            if (type == typeof(Double)) return value => new PropertyValue((Double)value);
+            if (type == typeof(Guid)) return value => new PropertyValue((Guid)value);
+            if (type == typeof(DateTime)) return value => new PropertyValue((DateTime)value);
+            if (type == typeof(DateTimeOffset)) return value => new PropertyValue((DateTimeOffset)value);
+            if (type == typeof(TimeSpan)) return value => new PropertyValue((TimeSpan)value);
+            if (type == typeof(Decimal)) return value => new PropertyValue((Decimal)value);
+
+            return value => new PropertyValue(value);
+        }
+
+
+        public object ReferenceValue
+        {
+            get
+            {
+                Contract.Assert(_scalarLength == 0, "This ReflectedValue refers to an unboxed value type, not a reference type or boxed value type.");
+                return _reference;
+            }
+        }
+
+        public Scalar ScalarValue
+        {
+            get
+            {
+                Contract.Assert(_scalarLength > 0, "This ReflectedValue refers to a reference type or boxed value type, not an unboxed value type");
+                return _scalar;
+            }
+        }
+
+        public int ScalarLength
+        {
+            get
+            {
+                Contract.Assert(_scalarLength > 0, "This ReflectedValue refers to a reference type or boxed value type, not an unboxed value type");
+                return _scalarLength;
+            }
+        }
+
+        /// <summary>
+        /// Gets a delegate that gets the value of a given property.
+        /// </summary>
+        public static Func<PropertyValue, PropertyValue> GetPropertyGetter(PropertyInfo property)
+        {
+            if (property.DeclaringType.GetTypeInfo().IsValueType)
+                return GetBoxedValueTypePropertyGetter(property);
+            else
+                return GetReferenceTypePropertyGetter(property);
+        }
+
+        /// <summary>
+        /// Gets a delegate that gets the value of a property of a value type.  We unfortunately cannot avoid boxing the value type,
+        /// without making this generic over the value type.  That would result in a large number of generic instantiations, and furthermore
+        /// does not work correctly on .Net Native (we cannot express the needed instantiations in an rd.xml file).  We expect that user-defined
+        /// value types will be rare, and in any case the boxing only happens for events that are actually enabled.
+        /// </summary>
+        private static Func<PropertyValue, PropertyValue> GetBoxedValueTypePropertyGetter(PropertyInfo property)
+        {
+            var type = property.PropertyType;
+
+            if (type.GetTypeInfo().IsEnum)
+                type = Enum.GetUnderlyingType(type);
+
+            var factory = GetFactory(type);
+
+            return container => factory(property.GetValue(container.ReferenceValue));
+        }
+
+        /// <summary>
+        /// For properties of reference types, we use a generic helper class to get the value.  This enables us to use MethodInfo.CreateDelegate
+        /// to build a fast getter.  We can get away with this on .Net Native, because we really only need one runtime instantiation of the
+        /// generic type, since it's only instantiated over reference types (and thus all instances are shared).
+        /// </summary>
+        /// <param name="property"></param>
+        /// <returns></returns>
+        private static Func<PropertyValue, PropertyValue> GetReferenceTypePropertyGetter(PropertyInfo property)
+        {
+            var helper = (TypeHelper)Activator.CreateInstance(typeof(ReferenceTypeHelper<>).MakeGenericType(property.DeclaringType));
+            return helper.GetPropertyGetter(property);
+        }
+
+        private abstract class TypeHelper
+        {
+            public abstract Func<PropertyValue, PropertyValue> GetPropertyGetter(PropertyInfo property);
+
+            protected Delegate GetGetMethod(PropertyInfo property, Type propertyType)
+            {
+                return property.GetMethod.CreateDelegate(typeof(Func<,>).MakeGenericType(property.DeclaringType, propertyType));
+            }
+        }
+
+        private sealed class ReferenceTypeHelper<TContainer> : TypeHelper where TContainer : class
+        {
+            public override Func<PropertyValue, PropertyValue> GetPropertyGetter(PropertyInfo property)
+            {
+                var type = property.PropertyType;
+
+                if (!Statics.IsValueType(type))
+                {
+                    var getter = (Func<TContainer, object>)GetGetMethod(property, type);
+                    return container => new PropertyValue(getter((TContainer)container.ReferenceValue));
+                }
+                else
+                {
+                    if (type.GetTypeInfo().IsEnum)
+                        type = Enum.GetUnderlyingType(type);
+
+                    if (type == typeof(Boolean)) { var f = (Func<TContainer, Boolean>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+                    if (type == typeof(Byte)) { var f = (Func<TContainer, Byte>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+                    if (type == typeof(SByte)) { var f = (Func<TContainer, SByte>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+                    if (type == typeof(Char)) { var f = (Func<TContainer, Char>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+                    if (type == typeof(Int16)) { var f = (Func<TContainer, Int16>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+                    if (type == typeof(UInt16)) { var f = (Func<TContainer, UInt16>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+                    if (type == typeof(Int32)) { var f = (Func<TContainer, Int32>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+                    if (type == typeof(UInt32)) { var f = (Func<TContainer, UInt32>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+                    if (type == typeof(Int64)) { var f = (Func<TContainer, Int64>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+                    if (type == typeof(UInt64)) { var f = (Func<TContainer, UInt64>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+                    if (type == typeof(IntPtr)) { var f = (Func<TContainer, IntPtr>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+                    if (type == typeof(UIntPtr)) { var f = (Func<TContainer, UIntPtr>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+                    if (type == typeof(Single)) { var f = (Func<TContainer, Single>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+                    if (type == typeof(Double)) { var f = (Func<TContainer, Double>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+                    if (type == typeof(Guid)) { var f = (Func<TContainer, Guid>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+                    if (type == typeof(DateTime)) { var f = (Func<TContainer, DateTime>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+                    if (type == typeof(DateTimeOffset)) { var f = (Func<TContainer, DateTimeOffset>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+                    if (type == typeof(TimeSpan)) { var f = (Func<TContainer, TimeSpan>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+                    if (type == typeof(Decimal)) { var f = (Func<TContainer, Decimal>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+
+                    return container => new PropertyValue(property.GetValue(container.ReferenceValue));
+                }
+            }
+        }
+    }
+}
index 7a613f4..19e9222 100644 (file)
@@ -18,30 +18,19 @@ namespace System.Diagnostics.Tracing
     /// Type of the top-level payload object. Should be EmptyStruct if the
     /// event has no payload.
     /// </typeparam>
-    internal class SimpleEventTypes<T>
-        : TraceLoggingEventTypes
+    internal static class SimpleEventTypes<T>
     {
-        private static SimpleEventTypes<T> instance;
+        private static TraceLoggingEventTypes instance;
 
-        internal readonly TraceLoggingTypeInfo<T> typeInfo;
-
-        private SimpleEventTypes(TraceLoggingTypeInfo<T> typeInfo)
-            : base(
-                typeInfo.Name,
-                typeInfo.Tags,
-                new TraceLoggingTypeInfo[] { typeInfo })
-        {
-            this.typeInfo = typeInfo;
-        }
-
-        public static SimpleEventTypes<T> Instance
+        public static TraceLoggingEventTypes Instance
         {
             get { return instance ?? InitInstance(); }
         }
 
-        private static SimpleEventTypes<T> InitInstance()
+        private static TraceLoggingEventTypes InitInstance()
         {
-            var newInstance = new SimpleEventTypes<T>(TraceLoggingTypeInfo<T>.Instance);
+            var info = TraceLoggingTypeInfo.GetInstance(typeof(T), null);
+            var newInstance = new TraceLoggingEventTypes(info.Name, info.Tags, new TraceLoggingTypeInfo[] { info });
             Interlocked.CompareExchange(ref instance, newInstance, null);
             return instance;
         }
index d262bdb..f6b621e 100644 (file)
 
 using System;
 using System.Collections.Generic;
+using System.Reflection;
 
-#if ES_BUILD_STANDALONE
-namespace Microsoft.Diagnostics.Tracing
-#else
-namespace System.Diagnostics.Tracing
-#endif
-{
-    #region NullTypeInfo
-
-    /// <summary>
-    /// TraceLogging: Type handler for empty or unsupported types.
-    /// </summary>
-    /// <typeparam name="DataType">The type to handle.</typeparam>
-    internal sealed class NullTypeInfo<DataType>
-        : TraceLoggingTypeInfo<DataType>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddGroup(name);
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref DataType value)
-        {
-            return;
-        }
-
-        public override object GetData(object value)
-        {
-            return null;
-        }
-    }
-
-    #endregion
-
-    #region Primitive scalars
-
-    /// <summary>
-    /// TraceLogging: Type handler for Boolean.
-    /// </summary>
-    internal sealed class BooleanTypeInfo
-        : TraceLoggingTypeInfo<Boolean>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.Format8(format, TraceLoggingDataType.Boolean8));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref Boolean value)
-        {
-            collector.AddScalar(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for Byte.
-    /// </summary>
-    internal sealed class ByteTypeInfo
-        : TraceLoggingTypeInfo<Byte>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.Format8(format, TraceLoggingDataType.UInt8));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref Byte value)
-        {
-            collector.AddScalar(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for SByte.
-    /// </summary>
-    internal sealed class SByteTypeInfo
-        : TraceLoggingTypeInfo<SByte>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.Format8(format, TraceLoggingDataType.Int8));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref SByte value)
-        {
-            collector.AddScalar(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for Int16.
-    /// </summary>
-    internal sealed class Int16TypeInfo
-        : TraceLoggingTypeInfo<Int16>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.Format16(format, TraceLoggingDataType.Int16));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref Int16 value)
-        {
-            collector.AddScalar(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for UInt16.
-    /// </summary>
-    internal sealed class UInt16TypeInfo
-        : TraceLoggingTypeInfo<UInt16>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.Format16(format, TraceLoggingDataType.UInt16));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref UInt16 value)
-        {
-            collector.AddScalar(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for Int32.
-    /// </summary>
-    internal sealed class Int32TypeInfo
-        : TraceLoggingTypeInfo<Int32>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.Format32(format, TraceLoggingDataType.Int32));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref Int32 value)
-        {
-            collector.AddScalar(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for UInt32.
-    /// </summary>
-    internal sealed class UInt32TypeInfo
-        : TraceLoggingTypeInfo<UInt32>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.Format32(format, TraceLoggingDataType.UInt32));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref UInt32 value)
-        {
-            collector.AddScalar(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for Int64.
-    /// </summary>
-    internal sealed class Int64TypeInfo
-        : TraceLoggingTypeInfo<Int64>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.Format64(format, TraceLoggingDataType.Int64));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref Int64 value)
-        {
-            collector.AddScalar(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for UInt64.
-    /// </summary>
-    internal sealed class UInt64TypeInfo
-        : TraceLoggingTypeInfo<UInt64>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.Format64(format, TraceLoggingDataType.UInt64));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref UInt64 value)
-        {
-            collector.AddScalar(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for IntPtr.
-    /// </summary>
-    internal sealed class IntPtrTypeInfo
-        : TraceLoggingTypeInfo<IntPtr>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.FormatPtr(format, Statics.IntPtrType));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref IntPtr value)
-        {
-            collector.AddScalar(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for UIntPtr.
-    /// </summary>
-    internal sealed class UIntPtrTypeInfo
-        : TraceLoggingTypeInfo<UIntPtr>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.FormatPtr(format, Statics.UIntPtrType));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref UIntPtr value)
-        {
-            collector.AddScalar(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for Double.
-    /// </summary>
-    internal sealed class DoubleTypeInfo
-        : TraceLoggingTypeInfo<Double>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.Format64(format, TraceLoggingDataType.Double));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref Double value)
-        {
-            collector.AddScalar(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for Single.
-    /// </summary>
-    internal sealed class SingleTypeInfo
-        : TraceLoggingTypeInfo<Single>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.Format32(format, TraceLoggingDataType.Float));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref Single value)
-        {
-            collector.AddScalar(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for Char.
-    /// </summary>
-    internal sealed class CharTypeInfo
-        : TraceLoggingTypeInfo<Char>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.Format16(format, TraceLoggingDataType.Char16));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref Char value)
-        {
-            collector.AddScalar(value);
-        }
-    }
-
-    #endregion
-
-    #region Primitive arrays
-
-    /// <summary>
-    /// TraceLogging: Type handler for Boolean[].
-    /// </summary>
-    internal sealed class BooleanArrayTypeInfo
-        : TraceLoggingTypeInfo<Boolean[]>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddArray(name, Statics.Format8(format, TraceLoggingDataType.Boolean8));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref Boolean[] value)
-        {
-            collector.AddArray(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for Byte[].
-    /// </summary>
-    internal sealed class ByteArrayTypeInfo
-        : TraceLoggingTypeInfo<Byte[]>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            switch (format)
-            {
-                default:
-                    collector.AddBinary(name, Statics.MakeDataType(TraceLoggingDataType.Binary, format));
-                    break;
-                case EventFieldFormat.String:
-                    collector.AddBinary(name, TraceLoggingDataType.CountedMbcsString);
-                    break;
-                case EventFieldFormat.Xml:
-                    collector.AddBinary(name, TraceLoggingDataType.CountedMbcsXml);
-                    break;
-                case EventFieldFormat.Json:
-                    collector.AddBinary(name, TraceLoggingDataType.CountedMbcsJson);
-                    break;
-                case EventFieldFormat.Boolean:
-                    collector.AddArray(name, TraceLoggingDataType.Boolean8);
-                    break;
-                case EventFieldFormat.Hexadecimal:
-                    collector.AddArray(name, TraceLoggingDataType.HexInt8);
-                    break;
-#if false 
-                case EventSourceFieldFormat.Signed:
-                    collector.AddArray(name, TraceLoggingDataType.Int8);
-                    break;
-                case EventSourceFieldFormat.Unsigned:
-                    collector.AddArray(name, TraceLoggingDataType.UInt8);
-                    break;
-#endif 
-            }
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref Byte[] value)
-        {
-            collector.AddBinary(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for SByte[].
-    /// </summary>
-    internal sealed class SByteArrayTypeInfo
-        : TraceLoggingTypeInfo<SByte[]>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddArray(name, Statics.Format8(format, TraceLoggingDataType.Int8));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref SByte[] value)
-        {
-            collector.AddArray(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for Int16[].
-    /// </summary>
-    internal sealed class Int16ArrayTypeInfo
-        : TraceLoggingTypeInfo<Int16[]>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddArray(name, Statics.Format16(format, TraceLoggingDataType.Int16));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref Int16[] value)
-        {
-            collector.AddArray(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for UInt16[].
-    /// </summary>
-    internal sealed class UInt16ArrayTypeInfo
-        : TraceLoggingTypeInfo<UInt16[]>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddArray(name, Statics.Format16(format, TraceLoggingDataType.UInt16));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref UInt16[] value)
-        {
-            collector.AddArray(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for Int32[].
-    /// </summary>
-    internal sealed class Int32ArrayTypeInfo
-        : TraceLoggingTypeInfo<Int32[]>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddArray(name, Statics.Format32(format, TraceLoggingDataType.Int32));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref Int32[] value)
-        {
-            collector.AddArray(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for UInt32[].
-    /// </summary>
-    internal sealed class UInt32ArrayTypeInfo
-        : TraceLoggingTypeInfo<UInt32[]>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddArray(name, Statics.Format32(format, TraceLoggingDataType.UInt32));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref UInt32[] value)
-        {
-            collector.AddArray(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for Int64[].
-    /// </summary>
-    internal sealed class Int64ArrayTypeInfo
-        : TraceLoggingTypeInfo<Int64[]>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddArray(name, Statics.Format64(format, TraceLoggingDataType.Int64));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref Int64[] value)
-        {
-            collector.AddArray(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for UInt64[].
-    /// </summary>
-    internal sealed class UInt64ArrayTypeInfo
-        : TraceLoggingTypeInfo<UInt64[]>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddArray(name, Statics.Format64(format, TraceLoggingDataType.UInt64));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref UInt64[] value)
-        {
-            collector.AddArray(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for IntPtr[].
-    /// </summary>
-    internal sealed class IntPtrArrayTypeInfo
-        : TraceLoggingTypeInfo<IntPtr[]>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddArray(name, Statics.FormatPtr(format, Statics.IntPtrType));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref IntPtr[] value)
-        {
-            collector.AddArray(value);
-        }
-    }
+#if !ES_BUILD_AGAINST_DOTNET_V35
+using Contract = System.Diagnostics.Contracts.Contract;
+#else
+using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
+#endif
 
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
     /// <summary>
-    /// TraceLogging: Type handler for UIntPtr[].
+    /// TraceLogging: Type handler for empty or unsupported types.
     /// </summary>
-    internal sealed class UIntPtrArrayTypeInfo
-        : TraceLoggingTypeInfo<UIntPtr[]>
+    internal sealed class NullTypeInfo : TraceLoggingTypeInfo
     {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddArray(name, Statics.FormatPtr(format, Statics.UIntPtrType));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref UIntPtr[] value)
-        {
-            collector.AddArray(value);
-        }
-    }
+        public NullTypeInfo() : base(typeof(EmptyStruct)) { }
 
-    /// <summary>
-    /// TraceLogging: Type handler for Char[].
-    /// </summary>
-    internal sealed class CharArrayTypeInfo
-        : TraceLoggingTypeInfo<Char[]>
-    {
         public override void WriteMetadata(
             TraceLoggingMetadataCollector collector,
             string name,
             EventFieldFormat format)
         {
-            collector.AddArray(name, Statics.Format16(format, TraceLoggingDataType.Char16));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref Char[] value)
-        {
-            collector.AddArray(value);
+            collector.AddGroup(name);
         }
-    }
 
-    /// <summary>
-    /// TraceLogging: Type handler for Double[].
-    /// </summary>
-    internal sealed class DoubleArrayTypeInfo
-        : TraceLoggingTypeInfo<Double[]>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
+        public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
         {
-            collector.AddArray(name, Statics.Format64(format, TraceLoggingDataType.Double));
+            return;
         }
 
-        public override void WriteData(TraceLoggingDataCollector collector, ref Double[] value)
+        public override object GetData(object value)
         {
-            collector.AddArray(value);
+            return null;
         }
     }
 
     /// <summary>
-    /// TraceLogging: Type handler for Single[].
+    /// Type handler for simple scalar types.
     /// </summary>
-    internal sealed class SingleArrayTypeInfo
-    : TraceLoggingTypeInfo<Single[]>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddArray(name, Statics.Format32(format, TraceLoggingDataType.Float));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref Single[] value)
-        {
-            collector.AddArray(value);
-        }
-    }
-
-    #endregion
-
-    #region Enum scalars
-
-    internal sealed class EnumByteTypeInfo<EnumType>
-        : TraceLoggingTypeInfo<EnumType>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.Format8(format, TraceLoggingDataType.UInt8));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref EnumType value)
-        {
-            collector.AddScalar(EnumHelper<Byte>.Cast(value));
-        }
-
-        public override object GetData(object value)
-        {
-            return value;
-        }
-    }
-
-    internal sealed class EnumSByteTypeInfo<EnumType>
-        : TraceLoggingTypeInfo<EnumType>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.Format8(format, TraceLoggingDataType.Int8));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref EnumType value)
-        {
-            collector.AddScalar(EnumHelper<SByte>.Cast(value));
-        }
-
-        public override object GetData(object value)
-        {
-            return value;
-        }
-    }
-
-    internal sealed class EnumInt16TypeInfo<EnumType>
-        : TraceLoggingTypeInfo<EnumType>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.Format16(format, TraceLoggingDataType.Int16));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref EnumType value)
-        {
-            collector.AddScalar(EnumHelper<Int16>.Cast(value));
-        }
-
-        public override object GetData(object value)
-        {
-            return value;
-        }
-    }
-
-    internal sealed class EnumUInt16TypeInfo<EnumType>
-        : TraceLoggingTypeInfo<EnumType>
+    sealed class ScalarTypeInfo : TraceLoggingTypeInfo
     {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.Format16(format, TraceLoggingDataType.UInt16));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref EnumType value)
-        {
-            collector.AddScalar(EnumHelper<UInt16>.Cast(value));
-        }
+        Func<EventFieldFormat, TraceLoggingDataType, TraceLoggingDataType> formatFunc;
+        TraceLoggingDataType nativeFormat;
 
-        public override object GetData(object value)
+        private ScalarTypeInfo(
+            Type type,
+            Func<EventFieldFormat, TraceLoggingDataType, TraceLoggingDataType> formatFunc,
+            TraceLoggingDataType nativeFormat) 
+            : base(type)
         {
-            return value;
+            this.formatFunc = formatFunc;
+            this.nativeFormat = nativeFormat;
         }
-    }
 
-    internal sealed class EnumInt32TypeInfo<EnumType>
-        : TraceLoggingTypeInfo<EnumType>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
+        public override void WriteMetadata(TraceLoggingMetadataCollector collector, string name, EventFieldFormat format)
         {
-            collector.AddScalar(name, Statics.Format32(format, TraceLoggingDataType.Int32));
+            collector.AddScalar(name, formatFunc(format, nativeFormat));
         }
 
-        public override void WriteData(TraceLoggingDataCollector collector, ref EnumType value)
+        public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
         {
-            collector.AddScalar(EnumHelper<Int32>.Cast(value));
+            collector.AddScalar(value);
         }
 
-        public override object GetData(object value)
-        {
-            return value;
-        }
+        public static TraceLoggingTypeInfo Boolean() { return new ScalarTypeInfo(typeof(Boolean), Statics.Format8, TraceLoggingDataType.Boolean8); }
+        public static TraceLoggingTypeInfo Byte() { return new ScalarTypeInfo(typeof(Byte), Statics.Format8, TraceLoggingDataType.UInt8); }
+        public static TraceLoggingTypeInfo SByte() { return new ScalarTypeInfo(typeof(SByte), Statics.Format8, TraceLoggingDataType.Int8); }
+        public static TraceLoggingTypeInfo Char() { return new ScalarTypeInfo(typeof(Char), Statics.Format16, TraceLoggingDataType.Char16); }
+        public static TraceLoggingTypeInfo Int16() { return new ScalarTypeInfo(typeof(Int16), Statics.Format16, TraceLoggingDataType.Int16); }
+        public static TraceLoggingTypeInfo UInt16() { return new ScalarTypeInfo(typeof(UInt16), Statics.Format16, TraceLoggingDataType.UInt16); }
+        public static TraceLoggingTypeInfo Int32() { return new ScalarTypeInfo(typeof(Int32), Statics.Format32, TraceLoggingDataType.Int32); }
+        public static TraceLoggingTypeInfo UInt32() { return new ScalarTypeInfo(typeof(UInt32), Statics.Format32, TraceLoggingDataType.UInt32); }
+        public static TraceLoggingTypeInfo Int64() { return new ScalarTypeInfo(typeof(Int64), Statics.Format64, TraceLoggingDataType.Int64); }
+        public static TraceLoggingTypeInfo UInt64() { return new ScalarTypeInfo(typeof(UInt64), Statics.Format64, TraceLoggingDataType.UInt64); }
+        public static TraceLoggingTypeInfo IntPtr() { return new ScalarTypeInfo(typeof(IntPtr), Statics.FormatPtr, Statics.IntPtrType); }
+        public static TraceLoggingTypeInfo UIntPtr() { return new ScalarTypeInfo(typeof(UIntPtr), Statics.FormatPtr, Statics.UIntPtrType); }
+        public static TraceLoggingTypeInfo Single() { return new ScalarTypeInfo(typeof(Single), Statics.Format32, TraceLoggingDataType.Float); }
+        public static TraceLoggingTypeInfo Double() { return new ScalarTypeInfo(typeof(Double), Statics.Format64, TraceLoggingDataType.Double); }
+        public static TraceLoggingTypeInfo Guid() { return new ScalarTypeInfo(typeof(Guid), (f, t) => Statics.MakeDataType(TraceLoggingDataType.Guid, f), TraceLoggingDataType.Guid); }
     }
 
-    internal sealed class EnumUInt32TypeInfo<EnumType>
-        : TraceLoggingTypeInfo<EnumType>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.Format32(format, TraceLoggingDataType.UInt32));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref EnumType value)
-        {
-            collector.AddScalar(EnumHelper<UInt32>.Cast(value));
-        }
-
-        public override object GetData(object value)
-        {
-            return value;
-        }
-    }
 
-    internal sealed class EnumInt64TypeInfo<EnumType>
-        : TraceLoggingTypeInfo<EnumType>
+    /// <summary>
+    /// Type handler for arrays of scalars
+    /// </summary>
+    internal sealed class ScalarArrayTypeInfo : TraceLoggingTypeInfo
     {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.Format64(format, TraceLoggingDataType.Int64));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref EnumType value)
-        {
-            collector.AddScalar(EnumHelper<Int64>.Cast(value));
-        }
+        Func<EventFieldFormat, TraceLoggingDataType, TraceLoggingDataType> formatFunc;
+        TraceLoggingDataType nativeFormat;
+        int elementSize;
 
-        public override object GetData(object value)
+        private ScalarArrayTypeInfo(
+            Type type,
+            Func<EventFieldFormat, TraceLoggingDataType, TraceLoggingDataType> formatFunc,
+            TraceLoggingDataType nativeFormat,
+            int elementSize) 
+            : base(type)
         {
-            return value;
+            this.formatFunc = formatFunc;
+            this.nativeFormat = nativeFormat;
+            this.elementSize = elementSize;
         }
-    }
 
-    internal sealed class EnumUInt64TypeInfo<EnumType>
-        : TraceLoggingTypeInfo<EnumType>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
+        public override void WriteMetadata(TraceLoggingMetadataCollector collector, string name, EventFieldFormat format)
         {
-            collector.AddScalar(name, Statics.Format64(format, TraceLoggingDataType.UInt64));
+            collector.AddArray(name, formatFunc(format, nativeFormat));
         }
 
-        public override void WriteData(TraceLoggingDataCollector collector, ref EnumType value)
+        public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
         {
-            collector.AddScalar(EnumHelper<UInt64>.Cast(value));
+            collector.AddArray(value, elementSize);
         }
 
-        public override object GetData(object value)
-        {
-            return value;
-        }
+        public static TraceLoggingTypeInfo Boolean() { return new ScalarArrayTypeInfo(typeof(Boolean[]), Statics.Format8, TraceLoggingDataType.Boolean8, sizeof(Boolean)); }
+        public static TraceLoggingTypeInfo Byte() { return new ScalarArrayTypeInfo(typeof(Byte[]), Statics.Format8, TraceLoggingDataType.UInt8, sizeof(Byte)); }
+        public static TraceLoggingTypeInfo SByte() { return new ScalarArrayTypeInfo(typeof(SByte[]), Statics.Format8, TraceLoggingDataType.Int8, sizeof(SByte)); }
+        public static TraceLoggingTypeInfo Char() { return new ScalarArrayTypeInfo(typeof(Char[]), Statics.Format16, TraceLoggingDataType.Char16, sizeof(Char)); }
+        public static TraceLoggingTypeInfo Int16() { return new ScalarArrayTypeInfo(typeof(Int16[]), Statics.Format16, TraceLoggingDataType.Int16, sizeof(Int16)); }
+        public static TraceLoggingTypeInfo UInt16() { return new ScalarArrayTypeInfo(typeof(UInt16[]), Statics.Format16, TraceLoggingDataType.UInt16, sizeof(UInt16)); }
+        public static TraceLoggingTypeInfo Int32() { return new ScalarArrayTypeInfo(typeof(Int32[]), Statics.Format32, TraceLoggingDataType.Int32, sizeof(Int32)); }
+        public static TraceLoggingTypeInfo UInt32() { return new ScalarArrayTypeInfo(typeof(UInt32[]), Statics.Format32, TraceLoggingDataType.UInt32, sizeof(UInt32)); }
+        public static TraceLoggingTypeInfo Int64() { return new ScalarArrayTypeInfo(typeof(Int64[]), Statics.Format64, TraceLoggingDataType.Int64, sizeof(Int64)); }
+        public static TraceLoggingTypeInfo UInt64() { return new ScalarArrayTypeInfo(typeof(UInt64[]), Statics.Format64, TraceLoggingDataType.UInt64, sizeof(UInt64)); }
+        public static TraceLoggingTypeInfo IntPtr() { return new ScalarArrayTypeInfo(typeof(IntPtr[]), Statics.FormatPtr, Statics.IntPtrType, System.IntPtr.Size); }
+        public static TraceLoggingTypeInfo UIntPtr() { return new ScalarArrayTypeInfo(typeof(UIntPtr[]), Statics.FormatPtr, Statics.UIntPtrType, System.IntPtr.Size); }
+        public static TraceLoggingTypeInfo Single() { return new ScalarArrayTypeInfo(typeof(Single[]), Statics.Format32, TraceLoggingDataType.Float, sizeof(Single)); }
+        public static TraceLoggingTypeInfo Double() { return new ScalarArrayTypeInfo(typeof(Double[]), Statics.Format64, TraceLoggingDataType.Double, sizeof(Double)); }
+        public unsafe static TraceLoggingTypeInfo Guid() { return new ScalarArrayTypeInfo(typeof(Guid), (f, t) => Statics.MakeDataType(TraceLoggingDataType.Guid, f), TraceLoggingDataType.Guid, sizeof(Guid)); }
     }
 
-    #endregion
-
-    #region Other built-in types
-
     /// <summary>
     /// TraceLogging: Type handler for String.
     /// </summary>
-    internal sealed class StringTypeInfo
-        : TraceLoggingTypeInfo<String>
+    internal sealed class StringTypeInfo : TraceLoggingTypeInfo
     {
+        public StringTypeInfo() : base(typeof(string)) { }
+
         public override void WriteMetadata(
             TraceLoggingMetadataCollector collector,
             string name,
@@ -832,67 +152,29 @@ namespace System.Diagnostics.Tracing
             collector.AddBinary(name, Statics.MakeDataType(TraceLoggingDataType.CountedUtf16String, format));
         }
 
-        public override void WriteData(TraceLoggingDataCollector collector, ref String value)
+        public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
         {
-            collector.AddBinary(value);
+            collector.AddBinary((string)value.ReferenceValue);
         }
         
         public override object GetData(object value)
         {
-            object val = base.GetData(value);
-            if (null == val)
-                val = "";
-
-            return val;
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for Guid.
-    /// </summary>
-    internal sealed class GuidTypeInfo
-        : TraceLoggingTypeInfo<Guid>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.MakeDataType(TraceLoggingDataType.Guid, format));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref Guid value)
-        {
-            collector.AddScalar(value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for Guid[].
-    /// </summary>
-    internal sealed class GuidArrayTypeInfo
-    : TraceLoggingTypeInfo<Guid[]>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddArray(name, Statics.MakeDataType(TraceLoggingDataType.Guid, format));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref Guid[] value)
-        {
-            collector.AddArray(value);
+            if(value == null)
+            {
+                return "";
+            }
+            
+            return value;
         }
     }
 
     /// <summary>
     /// TraceLogging: Type handler for DateTime.
     /// </summary>
-    internal sealed class DateTimeTypeInfo
-        : TraceLoggingTypeInfo<DateTime>
+    internal sealed class DateTimeTypeInfo : TraceLoggingTypeInfo
     {
+        public DateTimeTypeInfo() : base(typeof(DateTime)) { }
+
         public override void WriteMetadata(
             TraceLoggingMetadataCollector collector,
             string name,
@@ -901,9 +183,9 @@ namespace System.Diagnostics.Tracing
             collector.AddScalar(name, Statics.MakeDataType(TraceLoggingDataType.FileTime, format));
         }
 
-        public override void WriteData(TraceLoggingDataCollector collector, ref DateTime value)
+        public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
         {
-            var ticks = value.Ticks;
+            var ticks = value.ScalarValue.AsDateTime.Ticks;
             collector.AddScalar(ticks < 504911232000000000 ? 0 : ticks - 504911232000000000);
         }
     }
@@ -911,9 +193,10 @@ namespace System.Diagnostics.Tracing
     /// <summary>
     /// TraceLogging: Type handler for DateTimeOffset.
     /// </summary>
-    internal sealed class DateTimeOffsetTypeInfo
-        : TraceLoggingTypeInfo<DateTimeOffset>
+    internal sealed class DateTimeOffsetTypeInfo : TraceLoggingTypeInfo
     {
+        public DateTimeOffsetTypeInfo() : base(typeof(DateTimeOffset)) { }
+
         public override void WriteMetadata(TraceLoggingMetadataCollector collector, string name, EventFieldFormat format)
         {
             var group = collector.AddGroup(name);
@@ -921,20 +204,22 @@ namespace System.Diagnostics.Tracing
             group.AddScalar("Offset", TraceLoggingDataType.Int64);
         }
 
-        public override void WriteData(TraceLoggingDataCollector collector, ref DateTimeOffset value)
+        public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
         {
-            var ticks = value.Ticks;
+            var dateTimeOffset = value.ScalarValue.AsDateTimeOffset;
+            var ticks = dateTimeOffset.Ticks;
             collector.AddScalar(ticks < 504911232000000000 ? 0 : ticks - 504911232000000000);
-            collector.AddScalar(value.Offset.Ticks);
+            collector.AddScalar(dateTimeOffset.Offset.Ticks);
         }
     }
 
     /// <summary>
     /// TraceLogging: Type handler for TimeSpan.
     /// </summary>
-    internal sealed class TimeSpanTypeInfo
-        : TraceLoggingTypeInfo<TimeSpan>
+    internal sealed class TimeSpanTypeInfo : TraceLoggingTypeInfo
     {
+        public TimeSpanTypeInfo() : base(typeof(TimeSpan)) { }
+
         public override void WriteMetadata(
             TraceLoggingMetadataCollector collector,
             string name,
@@ -943,92 +228,50 @@ namespace System.Diagnostics.Tracing
             collector.AddScalar(name, Statics.MakeDataType(TraceLoggingDataType.Int64, format));
         }
 
-        public override void WriteData(TraceLoggingDataCollector collector, ref TimeSpan value)
+        public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
         {
-            collector.AddScalar(value.Ticks);
+            collector.AddScalar(value.ScalarValue.AsTimeSpan.Ticks);
         }
     }
 
     /// <summary>
     /// TraceLogging: Type handler for Decimal. (Note: not full-fidelity, exposed as Double.)
     /// </summary>
-    internal sealed class DecimalTypeInfo
-        : TraceLoggingTypeInfo<Decimal>
-    {
-        public override void WriteMetadata(
-            TraceLoggingMetadataCollector collector,
-            string name,
-            EventFieldFormat format)
-        {
-            collector.AddScalar(name, Statics.MakeDataType(TraceLoggingDataType.Double, format));
-        }
-
-        public override void WriteData(TraceLoggingDataCollector collector, ref decimal value)
-        {
-            collector.AddScalar((double)value);
-        }
-    }
-
-    /// <summary>
-    /// TraceLogging: Type handler for KeyValuePair.
-    /// </summary>
-    /// <typeparam name="K">Type of the KeyValuePair's Key property.</typeparam>
-    /// <typeparam name="V">Type of the KeyValuePair's Value property.</typeparam>
-    internal sealed class KeyValuePairTypeInfo<K, V>
-        : TraceLoggingTypeInfo<KeyValuePair<K, V>>
+    internal sealed class DecimalTypeInfo : TraceLoggingTypeInfo
     {
-        private readonly TraceLoggingTypeInfo<K> keyInfo;
-        private readonly TraceLoggingTypeInfo<V> valueInfo;
-
-        public KeyValuePairTypeInfo(List<Type> recursionCheck)
-        {
-            this.keyInfo = TraceLoggingTypeInfo<K>.GetInstance(recursionCheck);
-            this.valueInfo = TraceLoggingTypeInfo<V>.GetInstance(recursionCheck);
-        }
+        public DecimalTypeInfo() : base(typeof(Decimal)) { }
 
         public override void WriteMetadata(
             TraceLoggingMetadataCollector collector,
             string name,
             EventFieldFormat format)
         {
-            var group = collector.AddGroup(name);
-            this.keyInfo.WriteMetadata(group, "Key", EventFieldFormat.Default);
-            this.valueInfo.WriteMetadata(group, "Value", format);
-        }
-
-        public override void WriteData(
-            TraceLoggingDataCollector collector,
-            ref KeyValuePair<K, V> value)
-        {
-            var key = value.Key;
-            var val = value.Value;
-            this.keyInfo.WriteData(collector, ref key);
-            this.valueInfo.WriteData(collector, ref val);
+            collector.AddScalar(name, Statics.MakeDataType(TraceLoggingDataType.Double, format));
         }
 
-        public override object GetData(object value)
+        public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
         {
-            var serializedType = new Dictionary<string, object>();
-            var keyValuePair = (KeyValuePair<K, V>) value;
-            serializedType.Add("Key", this.keyInfo.GetData(keyValuePair.Key));
-            serializedType.Add("Value", this.valueInfo.GetData(keyValuePair.Value));
-            return serializedType;
+            collector.AddScalar((double)value.ScalarValue.AsDecimal);
         }
     }
 
     /// <summary>
     /// TraceLogging: Type handler for Nullable.
     /// </summary>
-    /// <typeparam name="T">Type of the Nullable's Value property.</typeparam>
-    internal sealed class NullableTypeInfo<T>
-        : TraceLoggingTypeInfo<Nullable<T>>
-        where T : struct
+    internal sealed class NullableTypeInfo : TraceLoggingTypeInfo
     {
-        private readonly TraceLoggingTypeInfo<T> valueInfo;
+        private readonly TraceLoggingTypeInfo valueInfo;
+        private readonly Func<PropertyValue, PropertyValue> hasValueGetter;
+        private readonly Func<PropertyValue, PropertyValue> valueGetter;
 
-        public NullableTypeInfo(List<Type> recursionCheck)
+        public NullableTypeInfo(Type type, List<Type> recursionCheck)
+            : base(type)
         {
-            this.valueInfo = TraceLoggingTypeInfo<T>.GetInstance(recursionCheck);
+            var typeArgs = type.GenericTypeArguments;
+            Contract.Assert(typeArgs.Length == 1);
+            this.valueInfo = TraceLoggingTypeInfo.GetInstance(typeArgs[0], recursionCheck);
+            this.hasValueGetter = PropertyValue.GetPropertyGetter(type.GetTypeInfo().GetDeclaredProperty("HasValue"));
+            this.valueGetter = PropertyValue.GetPropertyGetter(type.GetTypeInfo().GetDeclaredProperty("Value"));
         }
 
         public override void WriteMetadata(
@@ -1041,16 +284,12 @@ namespace System.Diagnostics.Tracing
             this.valueInfo.WriteMetadata(group, "Value", format);
         }
 
-        public override void WriteData(
-            TraceLoggingDataCollector collector,
-            ref Nullable<T> value)
+        public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
         {
-            var hasValue = value.HasValue;
+            var hasValue = hasValueGetter(value);
             collector.AddScalar(hasValue);
-            var val = hasValue ? value.Value : default(T);
-            this.valueInfo.WriteData(collector, ref val);
+            var val = hasValue.ScalarValue.AsBoolean ? valueGetter(value) : valueInfo.PropertyValueFactory(Activator.CreateInstance(valueInfo.DataType));
+            this.valueInfo.WriteData(collector, val);
         }
     }
-
-    #endregion
 }
index 8897ae2..af6a43f 100644 (file)
@@ -7,6 +7,8 @@ using System.Reflection;
 using System.Runtime.CompilerServices;
 using Encoding = System.Text.Encoding;
 
+using Microsoft.Reflection;
+
 #if ES_BUILD_STANDALONE
 using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
 namespace Microsoft.Diagnostics.Tracing
@@ -213,7 +215,7 @@ namespace System.Diagnostics.Tracing
                     return TraceLoggingDataType.Int8;
                 case EventSourceFieldFormat.Unsigned:
                     return TraceLoggingDataType.UInt8;
-#endif 
+#endif
                 default:
                     return MakeDataType(native, format);
             }
@@ -343,7 +345,7 @@ namespace System.Diagnostics.Tracing
                     return IntPtrType;
                 case EventSourceFieldFormat.Unsigned:
                     return UIntPtrType;
-#endif 
+#endif
                 default:
                     return MakeDataType(native, format);
             }
@@ -366,52 +368,32 @@ namespace System.Diagnostics.Tracing
 
         public static bool IsValueType(Type type)
         {
-            bool result;
-#if ES_BUILD_PCL
-            result = type.GetTypeInfo().IsValueType;
-#else
-            result = type.IsValueType;
-#endif
+            bool result = type.IsValueType();
             return result;
         }
 
         public static bool IsEnum(Type type)
         {
-            bool result;
-#if ES_BUILD_PCL
-            result = type.GetTypeInfo().IsEnum;
-#else
-            result = type.IsEnum;
-#endif
+            bool result = type.IsEnum();
             return result;
         }
 
         public static IEnumerable<PropertyInfo> GetProperties(Type type)
         {
-            IEnumerable<PropertyInfo> result;
-#if ES_BUILD_PCL
-            result = type.GetRuntimeProperties();
-#else
-            result = type.GetProperties();
-#endif
+            IEnumerable<PropertyInfo> result = type.GetProperties();
             return result;
         }
 
         public static MethodInfo GetGetMethod(PropertyInfo propInfo)
         {
-            MethodInfo result;
-#if ES_BUILD_PCL
-            result = propInfo.GetMethod;
-#else
-            result = propInfo.GetGetMethod();
-#endif
+            MethodInfo result = propInfo.GetGetMethod();
             return result;
         }
 
         public static MethodInfo GetDeclaredStaticMethod(Type declaringType, string name)
         {
             MethodInfo result;
-#if ES_BUILD_PCL
+#if (ES_BUILD_PCL || PROJECTN)
             result = declaringType.GetTypeInfo().GetDeclaredMethod(name);
 #else
             result = declaringType.GetMethod(
@@ -426,7 +408,7 @@ namespace System.Diagnostics.Tracing
             Type attributeType)
         {
             bool result;
-#if ES_BUILD_PCL
+#if (ES_BUILD_PCL || PROJECTN)
             result = propInfo.IsDefined(attributeType);
 #else
             var attributes = propInfo.GetCustomAttributes(
@@ -441,7 +423,7 @@ namespace System.Diagnostics.Tracing
             where AttributeType : Attribute
         {
             AttributeType result = null;
-#if ES_BUILD_PCL
+#if (ES_BUILD_PCL || PROJECTN)
             foreach (var attrib in propInfo.GetCustomAttributes<AttributeType>(false))
             {
                 result = attrib;
@@ -461,7 +443,7 @@ namespace System.Diagnostics.Tracing
             where AttributeType : Attribute
         {
             AttributeType result = null;
-#if ES_BUILD_PCL
+#if (ES_BUILD_PCL || PROJECTN)
             foreach (var attrib in type.GetTypeInfo().GetCustomAttributes<AttributeType>(false))
             {
                 result = attrib;
@@ -479,11 +461,7 @@ namespace System.Diagnostics.Tracing
 
         public static Type[] GetGenericArguments(Type type)
         {
-#if ES_BUILD_PCL
-            return type.GenericTypeArguments;
-#else
             return type.GetGenericArguments();
-#endif
         }
 
         public static Type FindEnumerableElementType(Type type)
@@ -496,19 +474,19 @@ namespace System.Diagnostics.Tracing
             }
             else
             {
-#if ES_BUILD_PCL
-            var ifaceTypes = type.GetTypeInfo().ImplementedInterfaces;
+#if (ES_BUILD_PCL || PROJECTN)
+                var ifaceTypes = type.GetTypeInfo().ImplementedInterfaces;
 #else
                 var ifaceTypes = type.FindInterfaces(IsGenericMatch, typeof(IEnumerable<>));
 #endif
 
                 foreach (var ifaceType in ifaceTypes)
                 {
-#if ES_BUILD_PCL
-                if (!IsGenericMatch(ifaceType, typeof(IEnumerable<>)))
-                {
-                    continue;
-                }
+#if (ES_BUILD_PCL || PROJECTN)
+                    if (!IsGenericMatch(ifaceType, typeof(IEnumerable<>)))
+                    {
+                        continue;
+                    }
 #endif
 
                     if (elementType != null)
@@ -527,19 +505,13 @@ namespace System.Diagnostics.Tracing
 
         public static bool IsGenericMatch(Type type, object openType)
         {
-            bool isGeneric;
-#if ES_BUILD_PCL
-            isGeneric = type.IsConstructedGenericType;
-#else
-            isGeneric = type.IsGenericType;
-#endif
-            return isGeneric && type.GetGenericTypeDefinition() == (Type)openType;
+            return type.IsGenericType() && type.GetGenericTypeDefinition() == (Type)openType;
         }
 
         public static Delegate CreateDelegate(Type delegateType, MethodInfo methodInfo)
         {
             Delegate result;
-#if ES_BUILD_PCL
+#if (ES_BUILD_PCL || PROJECTN)
             result = methodInfo.CreateDelegate(
                 delegateType);
 #else
@@ -550,279 +522,203 @@ namespace System.Diagnostics.Tracing
             return result;
         }
 
-        public static TraceLoggingTypeInfo GetTypeInfoInstance(Type dataType, List<Type> recursionCheck)
-        {
-            TraceLoggingTypeInfo result;
-
-            if (dataType == typeof(Int32))
-            {
-                result = TraceLoggingTypeInfo<Int32>.Instance;
-            }
-            else if (dataType == typeof(Int64))
-            {
-                result = TraceLoggingTypeInfo<Int64>.Instance;
-            }
-            else if (dataType == typeof(String))
-            {
-                result = TraceLoggingTypeInfo<String>.Instance;
-            }
-            else
-            {
-                var getInstanceInfo = Statics.GetDeclaredStaticMethod(
-                    typeof(TraceLoggingTypeInfo<>).MakeGenericType(dataType),
-                    "GetInstance");
-                var typeInfoObj = getInstanceInfo.Invoke(null, new object[] { recursionCheck });
-                result = (TraceLoggingTypeInfo)typeInfoObj;
-            }
-
-            return result;
-        }
-
-        public static TraceLoggingTypeInfo<DataType> CreateDefaultTypeInfo<DataType>(
+        public static TraceLoggingTypeInfo CreateDefaultTypeInfo(
+            Type dataType,
             List<Type> recursionCheck)
         {
             TraceLoggingTypeInfo result;
-            var dataType = typeof(DataType);
 
             if (recursionCheck.Contains(dataType))
             {
-                throw new NotSupportedException(Environment.GetResourceString("EventSource_RecursiveTypeDefinition"));
+                throw new NotSupportedException(Resources.GetResourceString("EventSource_RecursiveTypeDefinition"));
             }
 
             recursionCheck.Add(dataType);
 
             var eventAttrib = Statics.GetCustomAttribute<EventDataAttribute>(dataType);
             if (eventAttrib != null ||
-                Statics.GetCustomAttribute<CompilerGeneratedAttribute>(dataType) != null)
+                Statics.GetCustomAttribute<CompilerGeneratedAttribute>(dataType) != null ||
+                IsGenericMatch(dataType, typeof(KeyValuePair<,>)))
             {
                 var analysis = new TypeAnalysis(dataType, eventAttrib, recursionCheck);
-                result = new InvokeTypeInfo<DataType>(analysis);
+                result = new InvokeTypeInfo(dataType, analysis);
             }
             else if (dataType.IsArray)
             {
                 var elementType = dataType.GetElementType();
                 if (elementType == typeof(Boolean))
                 {
-                    result = new BooleanArrayTypeInfo();
+                    result = ScalarArrayTypeInfo.Boolean();
                 }
                 else if (elementType == typeof(Byte))
                 {
-                    result = new ByteArrayTypeInfo();
+                    result = ScalarArrayTypeInfo.Byte();
                 }
                 else if (elementType == typeof(SByte))
                 {
-                    result = new SByteArrayTypeInfo();
+                    result = ScalarArrayTypeInfo.SByte();
                 }
                 else if (elementType == typeof(Int16))
                 {
-                    result = new Int16ArrayTypeInfo();
+                    result = ScalarArrayTypeInfo.Int16();
                 }
                 else if (elementType == typeof(UInt16))
                 {
-                    result = new UInt16ArrayTypeInfo();
+                    result = ScalarArrayTypeInfo.UInt16();
                 }
                 else if (elementType == typeof(Int32))
                 {
-                    result = new Int32ArrayTypeInfo();
+                    result = ScalarArrayTypeInfo.Int32();
                 }
                 else if (elementType == typeof(UInt32))
                 {
-                    result = new UInt32ArrayTypeInfo();
+                    result = ScalarArrayTypeInfo.UInt32();
                 }
                 else if (elementType == typeof(Int64))
                 {
-                    result = new Int64ArrayTypeInfo();
+                    result = ScalarArrayTypeInfo.Int64();
                 }
                 else if (elementType == typeof(UInt64))
                 {
-                    result = new UInt64ArrayTypeInfo();
+                    result = ScalarArrayTypeInfo.UInt64();
                 }
                 else if (elementType == typeof(Char))
                 {
-                    result = new CharArrayTypeInfo();
+                    result = ScalarArrayTypeInfo.Char();
                 }
                 else if (elementType == typeof(Double))
                 {
-                    result = new DoubleArrayTypeInfo();
+                    result = ScalarArrayTypeInfo.Double();
                 }
                 else if (elementType == typeof(Single))
                 {
-                    result = new SingleArrayTypeInfo();
+                    result = ScalarArrayTypeInfo.Single();
                 }
                 else if (elementType == typeof(IntPtr))
                 {
-                    result = new IntPtrArrayTypeInfo();
+                    result = ScalarArrayTypeInfo.IntPtr();
                 }
                 else if (elementType == typeof(UIntPtr))
                 {
-                    result = new UIntPtrArrayTypeInfo();
+                    result = ScalarArrayTypeInfo.UIntPtr();
                 }
                 else if (elementType == typeof(Guid))
                 {
-                    result = new GuidArrayTypeInfo();
+                    result = ScalarArrayTypeInfo.Guid();
                 }
                 else
                 {
-                    result = (TraceLoggingTypeInfo<DataType>)CreateInstance(
-                        typeof(ArrayTypeInfo<>).MakeGenericType(elementType),
-                        GetTypeInfoInstance(elementType, recursionCheck));
+                    result = new ArrayTypeInfo(dataType, TraceLoggingTypeInfo.GetInstance(elementType, recursionCheck));
                 }
             }
-            else if (Statics.IsEnum(dataType))
+            else
             {
-                var underlyingType = Enum.GetUnderlyingType(dataType);
-                if (underlyingType == typeof(Int32))
+                if (Statics.IsEnum(dataType))
+                    dataType = Enum.GetUnderlyingType(dataType);
+
+                if (dataType == typeof(String))
                 {
-                    result = new EnumInt32TypeInfo<DataType>();
+                    result = new StringTypeInfo();
                 }
-                else if (underlyingType == typeof(UInt32))
+                else if (dataType == typeof(Boolean))
                 {
-                    result = new EnumUInt32TypeInfo<DataType>();
+                    result = ScalarTypeInfo.Boolean();
                 }
-                else if (underlyingType == typeof(Byte))
+                else if (dataType == typeof(Byte))
                 {
-                    result = new EnumByteTypeInfo<DataType>();
+                    result = ScalarTypeInfo.Byte();
                 }
-                else if (underlyingType == typeof(SByte))
+                else if (dataType == typeof(SByte))
                 {
-                    result = new EnumSByteTypeInfo<DataType>();
+                    result = ScalarTypeInfo.SByte();
                 }
-                else if (underlyingType == typeof(Int16))
+                else if (dataType == typeof(Int16))
                 {
-                    result = new EnumInt16TypeInfo<DataType>();
+                    result = ScalarTypeInfo.Int16();
                 }
-                else if (underlyingType == typeof(UInt16))
+                else if (dataType == typeof(UInt16))
                 {
-                    result = new EnumUInt16TypeInfo<DataType>();
+                    result = ScalarTypeInfo.UInt16();
                 }
-                else if (underlyingType == typeof(Int64))
+                else if (dataType == typeof(Int32))
                 {
-                    result = new EnumInt64TypeInfo<DataType>();
+                    result = ScalarTypeInfo.Int32();
                 }
-                else if (underlyingType == typeof(UInt64))
+                else if (dataType == typeof(UInt32))
                 {
-                    result = new EnumUInt64TypeInfo<DataType>();
+                    result = ScalarTypeInfo.UInt32();
                 }
-                else
+                else if (dataType == typeof(Int64))
                 {
-                    // Unexpected
-                    throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedEnumType", dataType.Name, underlyingType.Name));
+                    result = ScalarTypeInfo.Int64();
                 }
-            }
-            else if (dataType == typeof(String))
-            {
-                result = new StringTypeInfo();
-            }
-            else if (dataType == typeof(Boolean))
-            {
-                result = new BooleanTypeInfo();
-            }
-            else if (dataType == typeof(Byte))
-            {
-                result = new ByteTypeInfo();
-            }
-            else if (dataType == typeof(SByte))
-            {
-                result = new SByteTypeInfo();
-            }
-            else if (dataType == typeof(Int16))
-            {
-                result = new Int16TypeInfo();
-            }
-            else if (dataType == typeof(UInt16))
-            {
-                result = new UInt16TypeInfo();
-            }
-            else if (dataType == typeof(Int32))
-            {
-                result = new Int32TypeInfo();
-            }
-            else if (dataType == typeof(UInt32))
-            {
-                result = new UInt32TypeInfo();
-            }
-            else if (dataType == typeof(Int64))
-            {
-                result = new Int64TypeInfo();
-            }
-            else if (dataType == typeof(UInt64))
-            {
-                result = new UInt64TypeInfo();
-            }
-            else if (dataType == typeof(Char))
-            {
-                result = new CharTypeInfo();
-            }
-            else if (dataType == typeof(Double))
-            {
-                result = new DoubleTypeInfo();
-            }
-            else if (dataType == typeof(Single))
-            {
-                result = new SingleTypeInfo();
-            }
-            else if (dataType == typeof(DateTime))
-            {
-                result = new DateTimeTypeInfo();
-            }
-            else if (dataType == typeof(Decimal))
-            {
-                result = new DecimalTypeInfo();
-            }
-            else if (dataType == typeof(IntPtr))
-            {
-                result = new IntPtrTypeInfo();
-            }
-            else if (dataType == typeof(UIntPtr))
-            {
-                result = new UIntPtrTypeInfo();
-            }
-            else if (dataType == typeof(Guid))
-            {
-                result = new GuidTypeInfo();
-            }
-            else if (dataType == typeof(TimeSpan))
-            {
-                result = new TimeSpanTypeInfo();
-            }
-            else if (dataType == typeof(DateTimeOffset))
-            {
-                result = new DateTimeOffsetTypeInfo();
-            }
-            else if (dataType == typeof(EmptyStruct))
-            {
-                result = new NullTypeInfo<EmptyStruct>();
-            }
-            else if (IsGenericMatch(dataType, typeof(KeyValuePair<,>)))
-            {
-                var args = GetGenericArguments(dataType);
-                result = (TraceLoggingTypeInfo<DataType>)CreateInstance(
-                    typeof(KeyValuePairTypeInfo<,>).MakeGenericType(args[0], args[1]),
-                    recursionCheck);
-            }
-            else if (IsGenericMatch(dataType, typeof(Nullable<>)))
-            {
-                var args = GetGenericArguments(dataType);
-                result = (TraceLoggingTypeInfo<DataType>)CreateInstance(
-                    typeof(NullableTypeInfo<>).MakeGenericType(args[0]),
-                    recursionCheck);
-            }
-            else
-            {
-                var elementType = FindEnumerableElementType(dataType);
-                if (elementType != null)
+                else if (dataType == typeof(UInt64))
                 {
-                    result = (TraceLoggingTypeInfo<DataType>)CreateInstance(
-                        typeof(EnumerableTypeInfo<,>).MakeGenericType(dataType, elementType),
-                        GetTypeInfoInstance(elementType, recursionCheck));
+                    result = ScalarTypeInfo.UInt64();
+                }
+                else if (dataType == typeof(Char))
+                {
+                    result = ScalarTypeInfo.Char();
+                }
+                else if (dataType == typeof(Double))
+                {
+                    result = ScalarTypeInfo.Double();
+                }
+                else if (dataType == typeof(Single))
+                {
+                    result = ScalarTypeInfo.Single();
+                }
+                else if (dataType == typeof(DateTime))
+                {
+                    result = new DateTimeTypeInfo();
+                }
+                else if (dataType == typeof(Decimal))
+                {
+                    result = new DecimalTypeInfo();
+                }
+                else if (dataType == typeof(IntPtr))
+                {
+                    result = ScalarTypeInfo.IntPtr();
+                }
+                else if (dataType == typeof(UIntPtr))
+                {
+                    result = ScalarTypeInfo.UIntPtr();
+                }
+                else if (dataType == typeof(Guid))
+                {
+                    result = ScalarTypeInfo.Guid();
+                }
+                else if (dataType == typeof(TimeSpan))
+                {
+                    result = new TimeSpanTypeInfo();
+                }
+                else if (dataType == typeof(DateTimeOffset))
+                {
+                    result = new DateTimeOffsetTypeInfo();
+                }
+                else if (dataType == typeof(EmptyStruct))
+                {
+                    result = new NullTypeInfo();
+                }
+                else if (IsGenericMatch(dataType, typeof(Nullable<>)))
+                {
+                    result = new NullableTypeInfo(dataType, recursionCheck);
                 }
                 else
                 {
-                    throw new ArgumentException(Environment.GetResourceString("EventSource_NonCompliantTypeError", dataType.Name));
+                    var elementType = FindEnumerableElementType(dataType);
+                    if (elementType != null)
+                    {
+                        result = new EnumerableTypeInfo(dataType, TraceLoggingTypeInfo.GetInstance(elementType, recursionCheck));
+                    }
+                    else
+                    {
+                        throw new ArgumentException(Resources.GetResourceString("EventSource_NonCompliantTypeError", dataType.Name));
+                    }
                 }
             }
 
-            return (TraceLoggingTypeInfo<DataType>)result;
+            return result;
         }
 
         #endregion
index 2ac1df1..6a805d9 100644 (file)
@@ -60,70 +60,10 @@ namespace System.Diagnostics.Tracing
             return this;
         }
 
-        /// <summary>
-        /// Adds a Boolean value to the event payload.
-        /// </summary>
-        /// <param name="value">Value to be added.</param>
-        public void AddScalar(bool value)
-        {
-            DataCollector.ThreadInstance.AddScalar(&value, sizeof(bool));
-        }
-
-        /// <summary>
-        /// Adds an SByte value to the event payload.
-        /// </summary>
-        /// <param name="value">Value to be added.</param>
-        //[CLSCompliant(false)]
-        public void AddScalar(sbyte value)
-        {
-            DataCollector.ThreadInstance.AddScalar(&value, sizeof(sbyte));
-        }
-
-        /// <summary>
-        /// Adds a Byte value to the event payload.
-        /// </summary>
-        /// <param name="value">Value to be added.</param>
-        public void AddScalar(byte value)
-        {
-            DataCollector.ThreadInstance.AddScalar(&value, sizeof(byte));
-        }
-
-        /// <summary>
-        /// Adds an Int16 value to the event payload.
-        /// </summary>
-        /// <param name="value">Value to be added.</param>
-        public void AddScalar(short value)
-        {
-            DataCollector.ThreadInstance.AddScalar(&value, sizeof(short));
-        }
-
-        /// <summary>
-        /// Adds a UInt16 value to the event payload.
-        /// </summary>
-        /// <param name="value">Value to be added.</param>
-        //[CLSCompliant(false)]
-        public void AddScalar(ushort value)
-        {
-            DataCollector.ThreadInstance.AddScalar(&value, sizeof(ushort));
-        }
-
-        /// <summary>
-        /// Adds an Int32 value to the event payload.
-        /// </summary>
-        /// <param name="value">Value to be added.</param>
-        public void AddScalar(int value)
+        public void AddScalar(PropertyValue value)
         {
-            DataCollector.ThreadInstance.AddScalar(&value, sizeof(int));
-        }
-
-        /// <summary>
-        /// Adds a UInt32 value to the event payload.
-        /// </summary>
-        /// <param name="value">Value to be added.</param>
-        //[CLSCompliant(false)]
-        public void AddScalar(uint value)
-        {
-            DataCollector.ThreadInstance.AddScalar(&value, sizeof(uint));
+            var scalar = value.ScalarValue;
+            DataCollector.ThreadInstance.AddScalar(&scalar, value.ScalarLength);
         }
 
         /// <summary>
@@ -136,44 +76,6 @@ namespace System.Diagnostics.Tracing
         }
 
         /// <summary>
-        /// Adds a UInt64 value to the event payload.
-        /// </summary>
-        /// <param name="value">Value to be added.</param>
-        //[CLSCompliant(false)]
-        public void AddScalar(ulong value)
-        {
-            DataCollector.ThreadInstance.AddScalar(&value, sizeof(ulong));
-        }
-
-        /// <summary>
-        /// Adds an IntPtr value to the event payload.
-        /// </summary>
-        /// <param name="value">Value to be added.</param>
-        public void AddScalar(IntPtr value)
-        {
-            DataCollector.ThreadInstance.AddScalar(&value, IntPtr.Size);
-        }
-
-        /// <summary>
-        /// Adds a UIntPtr value to the event payload.
-        /// </summary>
-        /// <param name="value">Value to be added.</param>
-        //[CLSCompliant(false)]
-        public void AddScalar(UIntPtr value)
-        {
-            DataCollector.ThreadInstance.AddScalar(&value, UIntPtr.Size);
-        }
-
-        /// <summary>
-        /// Adds a Single value to the event payload.
-        /// </summary>
-        /// <param name="value">Value to be added.</param>
-        public void AddScalar(float value)
-        {
-            DataCollector.ThreadInstance.AddScalar(&value, sizeof(float));
-        }
-
-        /// <summary>
         /// Adds a Double value to the event payload.
         /// </summary>
         /// <param name="value">Value to be added.</param>
@@ -183,24 +85,6 @@ namespace System.Diagnostics.Tracing
         }
 
         /// <summary>
-        /// Adds a Char value to the event payload.
-        /// </summary>
-        /// <param name="value">Value to be added.</param>
-        public void AddScalar(char value)
-        {
-            DataCollector.ThreadInstance.AddScalar(&value, sizeof(char));
-        }
-
-        /// <summary>
-        /// Adds a Guid value to the event payload.
-        /// </summary>
-        /// <param name="value">Value to be added.</param>
-        public void AddScalar(Guid value)
-        {
-            DataCollector.ThreadInstance.AddScalar(&value, 16);
-        }
-
-        /// <summary>
         /// Adds a counted String value to the event payload.
         /// </summary>
         /// <param name="value">
@@ -211,185 +95,10 @@ namespace System.Diagnostics.Tracing
             DataCollector.ThreadInstance.AddBinary(value, value == null ? 0 : value.Length * 2);
         }
 
-        /// <summary>
-        /// Adds an array of Byte values to the event payload.
-        /// </summary>
-        /// <param name="value">
-        /// Value to be added. A null value is treated as a zero-length array.
-        /// </param>
-        public void AddBinary(byte[] value)
-        {
-            DataCollector.ThreadInstance.AddBinary(value, value == null ? 0 : value.Length);
-        }
-
-        /// <summary>
-        /// Adds an array of Boolean values to the event payload.
-        /// </summary>
-        /// <param name="value">
-        /// Value to be added. A null value is treated as a zero-length array.
-        /// </param>
-        public void AddArray(bool[] value)
-        {
-            DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(bool));
-        }
-
-        /// <summary>
-        /// Adds an array of SByte values to the event payload.
-        /// </summary>
-        /// <param name="value">
-        /// Value to be added. A null value is treated as a zero-length array.
-        /// </param>
-        //[CLSCompliant(false)]
-        public void AddArray(sbyte[] value)
-        {
-            DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(sbyte));
-        }
-
-        /// <summary>
-        /// Adds an array of Int16 values to the event payload.
-        /// </summary>
-        /// <param name="value">
-        /// Value to be added. A null value is treated as a zero-length array.
-        /// </param>
-        public void AddArray(short[] value)
-        {
-            DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(short));
-        }
-
-        /// <summary>
-        /// Adds an array of UInt16 values to the event payload.
-        /// </summary>
-        /// <param name="value">
-        /// Value to be added. A null value is treated as a zero-length array.
-        /// </param>
-        //[CLSCompliant(false)]
-        public void AddArray(ushort[] value)
-        {
-            DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(ushort));
-        }
-
-        /// <summary>
-        /// Adds an array of Int32 values to the event payload.
-        /// </summary>
-        /// <param name="value">
-        /// Value to be added. A null value is treated as a zero-length array.
-        /// </param>
-        public void AddArray(int[] value)
-        {
-            DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(int));
-        }
-
-        /// <summary>
-        /// Adds an array of UInt32 values to the event payload.
-        /// </summary>
-        /// <param name="value">
-        /// Value to be added. A null value is treated as a zero-length array.
-        /// </param>
-        //[CLSCompliant(false)]
-        public void AddArray(uint[] value)
-        {
-            DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(uint));
-        }
-
-        /// <summary>
-        /// Adds an array of Int64 values to the event payload.
-        /// </summary>
-        /// <param name="value">
-        /// Value to be added. A null value is treated as a zero-length array.
-        /// </param>
-        public void AddArray(long[] value)
-        {
-            DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(long));
-        }
-
-        /// <summary>
-        /// Adds an array of UInt64 values to the event payload.
-        /// </summary>
-        /// <param name="value">
-        /// Value to be added. A null value is treated as a zero-length array.
-        /// </param>
-        //[CLSCompliant(false)]
-        public void AddArray(ulong[] value)
-        {
-            DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(ulong));
-        }
-
-        /// <summary>
-        /// Adds an array of IntPtr values to the event payload.
-        /// </summary>
-        /// <param name="value">
-        /// Value to be added. A null value is treated as a zero-length array.
-        /// </param>
-        public void AddArray(IntPtr[] value)
-        {
-            DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, IntPtr.Size);
-        }
-
-        /// <summary>
-        /// Adds an array of UIntPtr values to the event payload.
-        /// </summary>
-        /// <param name="value">
-        /// Value to be added. A null value is treated as a zero-length array.
-        /// </param>
-        //[CLSCompliant(false)]
-        public void AddArray(UIntPtr[] value)
-        {
-            DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, UIntPtr.Size);
-        }
-
-        /// <summary>
-        /// Adds an array of Single values to the event payload.
-        /// </summary>
-        /// <param name="value">
-        /// Value to be added. A null value is treated as a zero-length array.
-        /// </param>
-        public void AddArray(float[] value)
-        {
-            DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(float));
-        }
-
-        /// <summary>
-        /// Adds an array of Double values to the event payload.
-        /// </summary>
-        /// <param name="value">
-        /// Value to be added. A null value is treated as a zero-length array.
-        /// </param>
-        public void AddArray(double[] value)
-        {
-            DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(double));
-        }
-
-        /// <summary>
-        /// Adds an array of Char values to the event payload.
-        /// </summary>
-        /// <param name="value">
-        /// Value to be added. A null value is treated as a zero-length array.
-        /// </param>
-        public void AddArray(char[] value)
-        {
-            DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(char));
-        }
-
-        /// <summary>
-        /// Adds an array of Guid values to the event payload.
-        /// </summary>
-        /// <param name="value">
-        /// Value to be added. A null value is treated as a zero-length array.
-        /// </param>
-        public void AddArray(Guid[] value)
-        {
-            DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, 16);
-        }
-
-        /// <summary>
-        /// Adds an array of Byte values to the event payload.
-        /// </summary>
-        /// <param name="value">
-        /// Value to be added. A null value is treated as a zero-length array.
-        /// </param>
-        public void AddCustom(byte[] value)
+        public void AddArray(PropertyValue value, int elementSize)
         {
-            DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(byte));
+            Array array = (Array)value.ReferenceValue;
+            DataCollector.ThreadInstance.AddArray(array, array == null ? 0 : array.Length, elementSize);
         }
     }
 }
index 9dd3d8c..366d615 100644 (file)
@@ -17,6 +17,7 @@
 
 #if ES_BUILD_STANDALONE
 using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
+using EventDescriptor = Microsoft.Diagnostics.Tracing.EventDescriptor;
 #endif
 
 using System;
@@ -120,8 +121,7 @@ namespace System.Diagnostics.Tracing
             }
 
             var options = new EventSourceOptions();
-            var data = new EmptyStruct();
-            this.WriteImpl(eventName, ref options, ref data, null, null);
+            this.WriteImpl(eventName, ref options, null, null, null, SimpleEventTypes<EmptyStruct>.Instance);
         }
 
         /// <summary>
@@ -148,8 +148,7 @@ namespace System.Diagnostics.Tracing
                 return;
             }
 
-            var data = new EmptyStruct();
-            this.WriteImpl(eventName, ref options, ref data, null, null);
+            this.WriteImpl(eventName, ref options, null, null, null, SimpleEventTypes<EmptyStruct>.Instance);
         }
 
         /// <summary>
@@ -182,7 +181,7 @@ namespace System.Diagnostics.Tracing
             }
 
             var options = new EventSourceOptions();
-            this.WriteImpl(eventName, ref options, ref data, null, null);
+            this.WriteImpl(eventName, ref options, data, null, null, SimpleEventTypes<T>.Instance);
         }
 
         /// <summary>
@@ -219,7 +218,7 @@ namespace System.Diagnostics.Tracing
                 return;
             }
 
-            this.WriteImpl(eventName, ref options, ref data, null, null);
+            this.WriteImpl(eventName, ref options, data, null, null, SimpleEventTypes<T>.Instance);
         }
 
         /// <summary>
@@ -258,7 +257,7 @@ namespace System.Diagnostics.Tracing
                 return;
             }
 
-            this.WriteImpl(eventName, ref options, ref data, null, null);
+            this.WriteImpl(eventName, ref options, data, null, null, SimpleEventTypes<T>.Instance);
         }
 
         /// <summary>
@@ -311,9 +310,10 @@ namespace System.Diagnostics.Tracing
                 this.WriteImpl(
                     eventName,
                     ref options,
-                    ref data,
+                    data,
                     pActivity,
-                    relatedActivityId == Guid.Empty ? null : pRelated);
+                    relatedActivityId == Guid.Empty ? null : pRelated,
+                    SimpleEventTypes<T>.Instance);
             }
         }
 
@@ -354,7 +354,7 @@ namespace System.Diagnostics.Tracing
             string eventName,
             ref EventSourceOptions options,
             TraceLoggingEventTypes eventTypes,
-             Guid* activityID, 
+             Guid* activityID,
              Guid* childActivityID,
             params object[] values)
         {
@@ -412,12 +412,12 @@ namespace System.Diagnostics.Tracing
         /// </param>
         [SecuritySafeCritical]
         private unsafe void WriteMultiMergeInner(
-        string eventName,
-        ref EventSourceOptions options,
-        TraceLoggingEventTypes eventTypes,
-        Guid* activityID, 
-        Guid* childActivityID,
-        params object[] values)
+            string eventName,
+            ref EventSourceOptions options,
+            TraceLoggingEventTypes eventTypes,
+            Guid* activityID,
+            Guid* childActivityID,
+            params object[] values)
         {
             int identity = 0;
             byte level = (options.valuesSet & EventSourceOptions.levelSet) != 0
@@ -455,7 +455,7 @@ namespace System.Diagnostics.Tracing
                 descriptors[1].SetMetadata(pMetadata1, nameInfo.nameMetadata.Length, 1);
                 descriptors[2].SetMetadata(pMetadata2, eventTypes.typeMetadata.Length, 1);
 
-#if !ES_BUILD_PCL
+#if (!ES_BUILD_PCL && !PROJECTN)
                 System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions();
 #endif
                 try
@@ -470,10 +470,12 @@ namespace System.Diagnostics.Tracing
 
                     for (int i = 0; i < eventTypes.typeInfos.Length; i++)
                     {
-                        eventTypes.typeInfos[i].WriteObjectData(TraceLoggingDataCollector.Instance, values[i]);
+                        var info = eventTypes.typeInfos[i];
+                        info.WriteData(TraceLoggingDataCollector.Instance, info.PropertyValueFactory(values[i]));
                     }
 
                     this.WriteEventRaw(
+                        eventName,
                         ref descriptor,
                         activityID,
                         childActivityID,
@@ -584,6 +586,7 @@ namespace System.Diagnostics.Tracing
                     }
 
                     this.WriteEventRaw(
+                        eventName,
                         ref descriptor,
                         activityID,
                         childActivityID,
@@ -594,17 +597,16 @@ namespace System.Diagnostics.Tracing
         }
 
         [SecuritySafeCritical]
-        private unsafe void WriteImpl<T>(
+        private unsafe void WriteImpl(
             string eventName,
             ref EventSourceOptions options,
-            ref T data,
+            object data,
             Guid* pActivityId,
-            Guid* pRelatedActivityId)
+            Guid* pRelatedActivityId,
+            TraceLoggingEventTypes eventTypes)
         {
             try
             {
-                var eventTypes = SimpleEventTypes<T>.Instance;
-
                 fixed (EventSourceOptions* pOptions = &options)
                 {
                     EventDescriptor descriptor;
@@ -629,7 +631,7 @@ namespace System.Diagnostics.Tracing
                         descriptors[1].SetMetadata(pMetadata1, nameInfo.nameMetadata.Length, 1);
                         descriptors[2].SetMetadata(pMetadata2, eventTypes.typeMetadata.Length, 1);
 
-#if !ES_BUILD_PCL
+#if (!ES_BUILD_PCL && !PROJECTN)
                         System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions();
 #endif
                         EventOpcode opcode = (EventOpcode)descriptor.Opcode;
@@ -663,9 +665,11 @@ namespace System.Diagnostics.Tracing
                                 pins,
                                 pinCount);
 
-                            eventTypes.typeInfo.WriteData(TraceLoggingDataCollector.Instance, ref data);
-                            
+                            var info = eventTypes.typeInfos[0];
+                            info.WriteData(TraceLoggingDataCollector.Instance, info.PropertyValueFactory(data));
+
                             this.WriteEventRaw(
+                                eventName,
                                 ref descriptor,
                                 pActivityId,
                                 pRelatedActivityId,
@@ -675,17 +679,17 @@ namespace System.Diagnostics.Tracing
                             // TODO enable filtering for listeners.
                             if (m_Dispatchers != null)
                             {
-                                var eventData = (EventPayload)(eventTypes.typeInfo.GetData(data));
+                                var eventData = (EventPayload)(eventTypes.typeInfos[0].GetData(data));
                                 WriteToAllListeners(eventName, ref descriptor, nameInfo.tags, pActivityId, eventData);
                             }
 
                         }
-                        catch(Exception ex)
+                        catch (Exception ex)
                         {
                             if (ex is EventSourceException)
                                 throw;
                             else
-                                ThrowEventSourceException(ex);
+                                ThrowEventSourceException(eventName, ex);
                         }
                         finally
                         {
@@ -699,7 +703,7 @@ namespace System.Diagnostics.Tracing
                 if (ex is EventSourceException)
                     throw;
                 else
-                    ThrowEventSourceException(ex);
+                    ThrowEventSourceException(eventName, ex);
             }
         }
 
@@ -727,7 +731,7 @@ namespace System.Diagnostics.Tracing
             DispatchToAllListeners(-1, pActivityId, eventCallbackArgs);
         }
 
-#if !ES_BUILD_PCL
+#if (!ES_BUILD_PCL && !PROJECTN)
         [System.Runtime.ConstrainedExecution.ReliabilityContract(
             System.Runtime.ConstrainedExecution.Consistency.WillNotCorruptState,
             System.Runtime.ConstrainedExecution.Cer.Success)]
@@ -761,9 +765,13 @@ namespace System.Diagnostics.Tracing
                         if (!byte.TryParse(etwTrait, out traitNum))
                         {
                             if (etwTrait == "GROUP")
+                            {
                                 traitNum = 1;
+                            }
                             else
-                                throw new ArgumentException(Environment.GetResourceString("UnknownEtwTrait", etwTrait), "traits");
+                            {
+                                throw new ArgumentException(Resources.GetResourceString("UnknownEtwTrait", etwTrait), "traits");
+                            }
                         }
                         string value = m_traits[i + 1];
                         int lenPos = traitMetaData.Count;
@@ -776,7 +784,7 @@ namespace System.Diagnostics.Tracing
                     }
                 }
                 providerMetadata = Statics.MetadataForString(this.Name, 0, traitMetaData.Count, 0);
-                int startPos = providerMetadata.Length-traitMetaData.Count;
+                int startPos = providerMetadata.Length - traitMetaData.Count;
                 foreach (var b in traitMetaData)
                     providerMetadata[startPos++] = b;
             }
@@ -803,16 +811,22 @@ namespace System.Diagnostics.Tracing
                     if (value[i] != ' ')        // Skip spaces between bytes.  
                     {
                         if (!(i + 1 < value.Length))
-                            throw new ArgumentException(Environment.GetResourceString("EvenHexDigits"), "traits");
+                        {
+                            throw new ArgumentException(Resources.GetResourceString("EvenHexDigits"), "traits");
+                        }
                         metaData.Add((byte)(HexDigit(value[i]) * 16 + HexDigit(value[i + 1])));
                         i++;
                     }
                 }
             }
             else if ('A' <= firstChar || ' ' == firstChar)  // Is it alphabetic or space (excludes digits and most punctuation). 
+            {
                 metaData.AddRange(Encoding.UTF8.GetBytes(value));
+            }
             else
-                throw new ArgumentException(Environment.GetResourceString("IllegalValue", value), "traits");
+            {
+                throw new ArgumentException(Resources.GetResourceString("IllegalValue", value), "traits");
+            }
 
             return metaData.Count - startPos;
         }
@@ -823,12 +837,19 @@ namespace System.Diagnostics.Tracing
         private static int HexDigit(char c)
         {
             if ('0' <= c && c <= '9')
+            {
                 return (c - '0');
+            }
             if ('a' <= c)
-                c = unchecked((char) (c - ('a' - 'A')));        // Convert to lower case
+            {
+                c = unchecked((char)(c - ('a' - 'A')));        // Convert to lower case
+            }
             if ('A' <= c && c <= 'F')
+            {
                 return (c - 'A' + 10);
-            throw new ArgumentException(Environment.GetResourceString("BadHexDigit", c), "traits");
+            }
+            
+            throw new ArgumentException(Resources.GetResourceString("BadHexDigit", c), "traits");
         }
 
         private NameInfo UpdateDescriptor(
index 06b840f..39327f6 100644 (file)
@@ -21,7 +21,7 @@ namespace System.Diagnostics.Tracing
     /// TraceLogging: Used when calling EventSource.WriteMultiMerge.
     /// Stores the type information to use when writing the event fields.
     /// </summary>
-    internal class TraceLoggingEventTypes
+    public class TraceLoggingEventTypes
     {
         internal readonly TraceLoggingTypeInfo[] typeInfos;
         internal readonly string name;
@@ -220,7 +220,7 @@ namespace System.Diagnostics.Tracing
             var result = new TraceLoggingTypeInfo[paramInfos.Length];
             for (int i = 0; i < paramInfos.Length; ++i)
             {
-                result[i] = Statics.GetTypeInfoInstance(paramInfos[i].ParameterType, recursionCheck);
+                result[i] = TraceLoggingTypeInfo.GetInstance(paramInfos[i].ParameterType, recursionCheck);
             }
 
             return result;
@@ -239,7 +239,7 @@ namespace System.Diagnostics.Tracing
             var result = new TraceLoggingTypeInfo[types.Length];
             for (int i = 0; i < types.Length; i++)
             {
-                result[i] = Statics.GetTypeInfoInstance(types[i], recursionCheck);
+                result[i] = TraceLoggingTypeInfo.GetInstance(types[i], recursionCheck);
             }
 
             return result;
index ff97db5..cee8985 100644 (file)
@@ -231,7 +231,7 @@ namespace System.Diagnostics.Tracing
 
             if (this.BeginningBufferedArray)
             {
-                throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedNestedArraysEnums"));
+                throw new NotSupportedException(Resources.GetResourceString("EventSource_NotSupportedNestedArraysEnums"));
             }
 
             this.impl.AddScalar(2);
@@ -243,7 +243,7 @@ namespace System.Diagnostics.Tracing
         {
             if (this.bufferedArrayFieldCount >= 0)
             {
-                throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedNestedArraysEnums"));
+                throw new NotSupportedException(Resources.GetResourceString("EventSource_NotSupportedNestedArraysEnums"));
             }
 
             this.bufferedArrayFieldCount = 0;
@@ -254,7 +254,7 @@ namespace System.Diagnostics.Tracing
         {
             if (this.bufferedArrayFieldCount != 1)
             {
-                throw new InvalidOperationException(Environment.GetResourceString("EventSource_IncorrentlyAuthoredTypeInfo"));
+                throw new InvalidOperationException(Resources.GetResourceString("EventSource_IncorrentlyAuthoredTypeInfo"));
             }
 
             this.bufferedArrayFieldCount = int.MinValue;
@@ -273,7 +273,7 @@ namespace System.Diagnostics.Tracing
         {
             if (this.BeginningBufferedArray)
             {
-                throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedCustomSerializedData"));
+                throw new NotSupportedException(Resources.GetResourceString("EventSource_NotSupportedCustomSerializedData"));
             }
 
             this.impl.AddScalar(2);
index 21a4390..7d4b533 100644 (file)
@@ -2,6 +2,7 @@
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
 using System;
+using System.Collections.Generic;
 
 #if !ES_BUILD_AGAINST_DOTNET_V35
 using Contract = System.Diagnostics.Contracts.Contract;
@@ -28,6 +29,7 @@ namespace System.Diagnostics.Tracing
         private readonly EventOpcode opcode = (EventOpcode)(-1);
         private readonly EventTags tags;
         private readonly Type dataType;
+        private readonly Func<object, PropertyValue> propertyValueFactory;
 
         internal TraceLoggingTypeInfo(Type dataType)
         {
@@ -40,6 +42,7 @@ namespace System.Diagnostics.Tracing
 
             this.name = dataType.Name;
             this.dataType = dataType;
+            this.propertyValueFactory = PropertyValue.GetFactory(dataType);
         }
 
         internal TraceLoggingTypeInfo(
@@ -70,6 +73,7 @@ namespace System.Diagnostics.Tracing
             this.opcode = opcode;
             this.tags = tags;
             this.dataType = dataType;
+            this.propertyValueFactory = PropertyValue.GetFactory(dataType);
         }
 
         /// <summary>
@@ -123,6 +127,11 @@ namespace System.Diagnostics.Tracing
             get { return this.dataType; }
         }
 
+        internal Func<object, PropertyValue> PropertyValueFactory
+        {
+            get { return this.propertyValueFactory; }
+        }
+
         /// <summary>
         /// When overridden by a derived class, writes the metadata (schema) for
         /// this type. Note that the sequence of operations in WriteMetadata should be
@@ -162,9 +171,9 @@ namespace System.Diagnostics.Tracing
         /// Refer to TraceLoggingTypeInfo.WriteObjectData for information about this
         /// method.
         /// </param>
-        public abstract void WriteObjectData(
+        public abstract void WriteData(
             TraceLoggingDataCollector collector,
-            object value);
+            PropertyValue value);
 
         /// <summary>
         /// Fetches the event parameter data for internal serialization. 
@@ -175,5 +184,25 @@ namespace System.Diagnostics.Tracing
         {
             return value;
         }
+
+        [ThreadStatic] // per-thread cache to avoid synchronization
+        private static Dictionary<Type, TraceLoggingTypeInfo> threadCache;
+
+        public static TraceLoggingTypeInfo GetInstance(Type type, List<Type> recursionCheck)
+        {
+            var cache = threadCache ?? (threadCache = new Dictionary<Type, TraceLoggingTypeInfo>());
+
+            TraceLoggingTypeInfo instance;
+            if (!cache.TryGetValue(type, out instance))
+            {
+                if (recursionCheck == null)
+                    recursionCheck = new List<Type>();
+                var recursionCheckCount = recursionCheck.Count;
+                instance = Statics.CreateDefaultTypeInfo(type, recursionCheck);
+                cache[type] = instance;
+                recursionCheck.RemoveRange(recursionCheckCount, recursionCheck.Count - recursionCheckCount);
+            }
+            return instance;
+        }
     }
 }
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingTypeInfo_T.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingTypeInfo_T.cs
deleted file mode 100644 (file)
index 5894598..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Collections.Generic;
-using Interlocked = System.Threading.Interlocked;
-
-#if ES_BUILD_STANDALONE
-namespace Microsoft.Diagnostics.Tracing
-#else
-namespace System.Diagnostics.Tracing
-#endif
-{
-    /// <summary>
-    /// TraceLogging: used when implementing a custom TraceLoggingTypeInfo.
-    /// Implementations of this type provide the behaviors that TraceLogging
-    /// uses to turn objects into event data. TraceLogging provides default
-    /// implementations of this type, but custom implementations can be used
-    /// when the default TraceLogging implementation is insufficient.
-    /// </summary>
-    /// <typeparam name="DataType">
-    /// The type of object that is handled by this implementation.
-    /// </typeparam>
-    internal abstract class TraceLoggingTypeInfo<DataType>
-        : TraceLoggingTypeInfo
-    {
-        private static TraceLoggingTypeInfo<DataType> instance;
-
-        /// <summary>
-        /// Initializes a new instance of the TraceLoggingTypeInfo class with
-        /// default settings. Uses typeof(DataType).Name for EventName and FieldName.
-        /// Marks Level and Opcode as unset. Sets Keywords and Traits to 0.
-        /// </summary>
-        protected TraceLoggingTypeInfo()
-            : base(typeof(DataType))
-        {
-            return;
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the TraceLoggingTypeInfo class, using
-        /// the specified values for the EventName, Level, Opcode, Keywords,
-        /// FieldName, and Traits properties.
-        /// </summary>
-        /// <param name="name">
-        /// The value for the Name property. Must not contain '\0' characters.
-        /// Must not be null.
-        /// </param>
-        /// <param name="level">
-        /// The value for the Level property, or -1 to mark Level as unset.
-        /// </param>
-        /// <param name="opcode">
-        /// The value for the Opcode property, or -1 to mark Opcode as unset.
-        /// </param>
-        /// <param name="keywords">
-        /// The value for the Keywords property.
-        /// </param>
-        /// <param name="tags">
-        /// The value for the Tags property.
-        /// </param>
-        protected TraceLoggingTypeInfo(
-            string name,
-            EventLevel level,
-            EventOpcode opcode,
-            EventKeywords keywords,
-            EventTags tags)
-        : base(
-            typeof(DataType),
-            name,
-            level,
-            opcode,
-            keywords,
-            tags)
-        {
-            return;
-        }
-
-        /// <summary>
-        /// Gets the type info that will be used for handling instances of
-        /// DataType. If the instance has not already been set, this will
-        /// call TrySetInstance(automaticSerializer) to set one, where
-        /// automaticSerializer is the value returned from CreateDefault(),
-        /// or a do-nothing serializer if CreateDefault() fails.
-        /// </summary>
-        public static TraceLoggingTypeInfo<DataType> Instance
-        {
-            get
-            {
-                return instance ?? InitInstance();
-            }
-        }
-
-        /// <summary>
-        /// When overridden by a derived class, writes the data (fields) for an instance
-        /// of DataType. Note that the sequence of operations in WriteData should be
-        /// essentially identical to the sequence of operations in WriteMetadata. Otherwise,
-        /// the metadata and data will not match, which may cause trouble when decoding the
-        /// event.
-        /// </summary>
-        /// <param name="collector">
-        /// The object that collects the data for the instance. Data is written by calling
-        /// methods on the collector object. Note that if the type contains sub-objects,
-        /// the implementation of this method may need to call the WriteData method
-        /// for the sub-object, e.g. by calling
-        /// TraceLoggingTypeInfo&lt;SubType&gt;.Instance.WriteData(...).
-        /// </param>
-        /// <param name="value">
-        /// The value for which data is to be written.
-        /// </param>
-        public abstract void WriteData(
-            TraceLoggingDataCollector collector,
-            ref DataType value);
-
-        /// <summary>
-        /// When overridden in a derived class, writes the data (fields) for an instance
-        /// of DataType. The default implementation of WriteObjectData calls
-        /// WriteData(collector, (DataType)value). Normally, you will override WriteData
-        /// and not WriteObjectData. However, if your implementation of WriteData has to
-        /// cast the value to object, it may be more efficient to reverse this calling
-        /// pattern, i.e. to implement WriteObjectData, and then implement WriteData as a
-        /// call to WriteObjectData.
-        /// </summary>
-        /// <param name="collector">
-        /// The object that collects the data for the instance. Data is written by calling
-        /// methods on the collector object. Note that if the type contains sub-objects,
-        /// the implementation of this method may need to call the WriteData method
-        /// for the sub-object, e.g. by calling
-        /// TraceLoggingTypeInfo&lt;SubType&gt;.Instance.WriteData(...).
-        /// </param>
-        /// <param name="value">
-        /// The value for which data is to be written. Note that this value may be null
-        /// (even for value types) if the property from which the value was read is
-        /// missing or null.
-        /// </param>
-        public override void WriteObjectData(
-            TraceLoggingDataCollector collector,
-            object value)
-        {
-            var val = value == null ? default(DataType) : (DataType)value;
-            this.WriteData(collector, ref val);
-        }
-
-        internal static TraceLoggingTypeInfo<DataType> GetInstance(List<Type> recursionCheck)
-        {
-            if (instance == null)
-            {
-                var recursionCheckCount = recursionCheck.Count;
-                var newInstance = Statics.CreateDefaultTypeInfo<DataType>(recursionCheck);
-                Interlocked.CompareExchange(ref instance, newInstance, null);
-                recursionCheck.RemoveRange(recursionCheckCount, recursionCheck.Count - recursionCheckCount);
-            }
-
-            return instance;
-        }
-
-        private static TraceLoggingTypeInfo<DataType> InitInstance()
-        {
-            return GetInstance(new List<Type>());
-        }
-    }
-}
index 8b44dde..3221dbd 100644 (file)
@@ -57,7 +57,7 @@ namespace System.Diagnostics.Tracing
                 }
 
                 var propertyType = propertyInfo.PropertyType;
-                var propertyTypeInfo = Statics.GetTypeInfoInstance(propertyType, recursionCheck);
+                var propertyTypeInfo = TraceLoggingTypeInfo.GetInstance(propertyType, recursionCheck);
                 var fieldAttribute = Statics.GetCustomAttribute<EventFieldAttribute>(propertyInfo);
 
                 string propertyName =
@@ -68,7 +68,7 @@ namespace System.Diagnostics.Tracing
                     : propertyInfo.Name;
                 propertyList.Add(new PropertyAnalysis(
                     propertyName,
-                    getterInfo,
+                    propertyInfo,
                     propertyTypeInfo,
                     fieldAttribute));
             }
index 9971a8f..31e5a68 100644 (file)
@@ -24,7 +24,8 @@ namespace System.Diagnostics.Tracing
     /// <summary>
     /// WindowsEventLevel. Custom values must be in the range from 16 through 255
     /// </summary>
-    public enum EventLevel {
+    public enum EventLevel
+    {
         /// <summary>
         /// Log always
         /// </summary>
@@ -53,10 +54,11 @@ namespace System.Diagnostics.Tracing
     /// <summary>
     /// WindowsEventTask. Custom values must be in the range from 1 through 65534
     /// </summary>
-#if !ES_BUILD_STANDALONE
+#if (!ES_BUILD_STANDALONE && !PROJECTN)
     [System.Runtime.CompilerServices.FriendAccessAllowed]
 #endif
-    public enum EventTask {
+    public enum EventTask
+    {
         /// <summary>
         /// Undefined task
         /// </summary>
@@ -65,7 +67,7 @@ namespace System.Diagnostics.Tracing
     /// <summary>
     /// EventOpcode. Custom values must be in the range from 11 through 239
     /// </summary>
-#if !ES_BUILD_STANDALONE
+#if (!ES_BUILD_STANDALONE && !PROJECTN)
     [System.Runtime.CompilerServices.FriendAccessAllowed]
 #endif
     public enum EventOpcode
@@ -120,12 +122,12 @@ namespace System.Diagnostics.Tracing
     /// <summary>
     /// EventChannel. Custom values must be in the range from 16 through 255. Currently only predefined values allowed.
     /// </summary>
-    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1028:EnumStorageShouldBeInt32", Justification="Backwards compatibility")]
-#if !ES_BUILD_STANDALONE
+    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1028:EnumStorageShouldBeInt32", Justification = "Backwards compatibility")]
+#if (!ES_BUILD_STANDALONE && !PROJECTN)
     [System.Runtime.CompilerServices.FriendAccessAllowed]
 #endif
-    public enum EventChannel : byte 
-    { 
+    public enum EventChannel : byte
+    {
         /// <summary>
         /// No channel
         /// </summary>
@@ -146,7 +148,8 @@ namespace System.Diagnostics.Tracing
     /// EventOpcode
     /// </summary>
     [Flags]
-    public enum EventKeywords : long {
+    public enum EventKeywords : long
+    {
         /// <summary>
         /// No events. 
         /// </summary>