Exemple #1
0
        // Use reflection to look at the attributes of a class, and generate a manifest for it (as UTF8) and
        // return the UTF8 bytes.  It also sets up the code:EventData structures needed to dispatch events
        // at run time.  'source' is the event source to place the descriptors.  If it is null,
        // then the descriptors are not creaed, and just the manifest is generated.  
        private static byte[] CreateManifestAndDescriptors(Type eventSourceType, string eventSourceDllName, EventSource source)
        {
            MethodInfo[] methods = eventSourceType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
            EventAttribute defaultEventAttribute;
            int eventId = 1;        // The number given to an event that does not have a explicitly given ID. 
            EventMetadata[] eventData = null;
            Dictionary<string, string> eventsByName = null;
            if (source != null)
                eventData = new EventMetadata[methods.Length];

            // See if we have localization information.  
            ResourceManager resources = null;
            EventSourceAttribute eventSourceAttrib = (EventSourceAttribute)GetCustomAttributeHelper(eventSourceType, typeof(EventSourceAttribute));
            if (eventSourceAttrib != null && eventSourceAttrib.LocalizationResources != null)
                resources = new ResourceManager(eventSourceAttrib.LocalizationResources, eventSourceType.Assembly);

            ManifestBuilder manifest = new ManifestBuilder(GetName(eventSourceType), GetGuid(eventSourceType), eventSourceDllName, resources);

            // Collect task, opcode, keyword and channel information
#if FEATURE_MANAGED_ETW_CHANNELS
            foreach (var providerEnumKind in new string[] { "Keywords", "Tasks", "Opcodes", "Channels" })
#else
            foreach (var providerEnumKind in new string[] { "Keywords", "Tasks", "Opcodes" })
#endif
            {
                Type nestedType = eventSourceType.GetNestedType(providerEnumKind);
                if (nestedType != null)
                {
                    foreach (FieldInfo staticField in nestedType.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static))
                    {
                        AddProviderEnumKind(manifest, staticField, providerEnumKind);
                    }
                }
            }

            for (int i = 0; i < methods.Length; i++)
            {
                MethodInfo method = methods[i];
                ParameterInfo[] args = method.GetParameters();

                // Get the EventDescriptor (from the Custom attributes)
                EventAttribute eventAttribute = (EventAttribute)GetCustomAttributeHelper(method, typeof(EventAttribute));

                // Methods that don't return void can't be events.  
                if (method.ReturnType != typeof(void))
                {
                    if (eventAttribute != null)
                        throw new ArgumentException(Environment.GetResourceString("EventSource_AttributeOnNonVoid", method.Name));
                    continue;
                }
                if (method.IsVirtual || method.IsStatic)
                {
                    continue;
                }

                if (eventAttribute == null)
                {
                    // If we explictly mark the method as not being an event, then honor that.  
                    if (GetCustomAttributeHelper(method, typeof(NonEventAttribute)) != null)
                        continue;

                    defaultEventAttribute = new EventAttribute(eventId);
                    eventAttribute = defaultEventAttribute;
                }
                else if (eventAttribute.EventId <= 0)
                    throw new ArgumentException(Environment.GetResourceString("EventSource_NeedPositiveId"));
                else if ((ulong)eventAttribute.Keywords >= 0x0000100000000000UL)
                    throw new ArgumentException(Environment.GetResourceString("EventSource_ReservedKeywords"));
                eventId++;

                // Auto-assign tasks, starting with the highest task number and working back 
                if (eventAttribute.Opcode == EventOpcode.Info && eventAttribute.Task == EventTask.None)
                    eventAttribute.Task = (EventTask)(0xFFFE - eventAttribute.EventId);

                manifest.StartEvent(method.Name, eventAttribute);
                for (int fieldIdx = 0; fieldIdx < args.Length; fieldIdx++)
                {
                    // If the first parameter is 'RelatedActivityId' then skip it.  
                    if (fieldIdx == 0 && args[fieldIdx].ParameterType == typeof(Guid) && 
                        string.Compare(args[fieldIdx].Name, "RelatedActivityId", StringComparison.OrdinalIgnoreCase) == 0)
                        continue;
                    manifest.AddEventParameter(args[fieldIdx].ParameterType, args[fieldIdx].Name);
                }
                manifest.EndEvent();

                if (source != null)
                {
                    // Do checking for user errors (optional, but nto a big deal so we do it).  
                    DebugCheckEvent(ref eventsByName, eventData, method, eventAttribute);
                    AddEventDescriptor(ref eventData, method.Name, eventAttribute, args);
                }
            }

            if (source != null)
            {
                TrimEventDescriptors(ref eventData);
                source.m_eventData = eventData;     // officaly initialize it. We do this at most once (it is racy otherwise). 
            }

            return manifest.CreateManifest();
        }