protected virtual IEnumerable<InstrumentationTarget> GetInstrumentationSet(ITypeDetails t, InstrumentAttribute context) { var toReturn = new List<InstrumentationTarget>(); if (!t.IsGenericTypeDefinition) { // Does the type have an Instrument attribute? var typeLevelAttribute = t.InstrumentationContext; typeLevelAttribute = InstrumentAttribute.GetEffectiveInstrumentationContext(typeLevelAttribute, context); if (t.IsCompilerGenerated && (typeLevelAttribute == null || !typeLevelAttribute.IncludeCompilerGeneratedCode)) { // Bail out early - we've found a compiler-generated method and haven't been told to include 'em _logger.DebugFormat("Skipping type {0} - compiler-generated and configuration set to skip", t.FullName); return toReturn; } _logger.DebugFormat("Processing type {0}", t.FullName); var baseBindingFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; var propBindingFlags = baseBindingFlags; var methodBindingFlags = baseBindingFlags; var ctorBindingFlags = baseBindingFlags; if (typeLevelAttribute == null) { propBindingFlags |= BindingFlags.NonPublic | BindingFlags.Public; methodBindingFlags |= BindingFlags.NonPublic | BindingFlags.Public; ctorBindingFlags |= BindingFlags.NonPublic | BindingFlags.Public; } else { if ((typeLevelAttribute.Scopes & InstrumentationScopes.PublicProperties) == InstrumentationScopes.PublicProperties) { propBindingFlags |= BindingFlags.Public; } if ((typeLevelAttribute.Scopes & InstrumentationScopes.NonPublicProperties) == InstrumentationScopes.NonPublicProperties) { propBindingFlags |= BindingFlags.NonPublic; } if ((typeLevelAttribute.Scopes & InstrumentationScopes.PublicMethods) == InstrumentationScopes.PublicMethods) { methodBindingFlags |= BindingFlags.Public; } if ((typeLevelAttribute.Scopes & InstrumentationScopes.NonPublicMethods) == InstrumentationScopes.NonPublicMethods) { methodBindingFlags |= BindingFlags.NonPublic; } if ((typeLevelAttribute.Scopes & InstrumentationScopes.PublicConstructors) == InstrumentationScopes.PublicConstructors) { ctorBindingFlags |= BindingFlags.Public; } if ((typeLevelAttribute.Scopes & InstrumentationScopes.NonPublicConstructors) == InstrumentationScopes.NonPublicConstructors) { ctorBindingFlags |= BindingFlags.NonPublic; } } _logger.DebugFormat("Prop flags {0}, Ctor flags {1}, Method flags {2}", propBindingFlags, ctorBindingFlags, methodBindingFlags); // Instrument everything in this type, irrespective of its member-level // details foreach (var methodDetails in t.GetMethods(methodBindingFlags)) { _logger.DebugFormat("Examining method {0}", methodDetails.ToString()); var attr = InstrumentAttribute.GetEffectiveInstrumentationContext(methodDetails.InstrumentationContext, typeLevelAttribute); if (attr != null && (!methodDetails.IsCompilerGenerated || attr.IncludeCompilerGeneratedCode)) { toReturn.Add(GetInstrumentationTarget(methodDetails, attr)); } } foreach (var propertyDetails in t.GetProperties(propBindingFlags)) { _logger.DebugFormat("Examining property {0}.{1}", t.FullName, propertyDetails.Name); var getMethod = propertyDetails.GetMethod; var setMethod = propertyDetails.SetMethod; if (getMethod != null && getMethod.ContainsGenericParameters) { getMethod = null; } if (setMethod != null && setMethod.ContainsGenericParameters) { setMethod = null; } if (getMethod != null) { var getMethodAttr = InstrumentAttribute.GetEffectiveInstrumentationContext(propertyDetails.InstrumentationContext, getMethod.InstrumentationContext, typeLevelAttribute); if (getMethodAttr != null) { toReturn.Add(GetInstrumentationTarget(getMethod, getMethodAttr)); } } if (setMethod != null) { var setMethodAttr = InstrumentAttribute.GetEffectiveInstrumentationContext(propertyDetails.InstrumentationContext, setMethod.InstrumentationContext, typeLevelAttribute); if (setMethodAttr != null) { toReturn.Add(GetInstrumentationTarget(setMethod, setMethodAttr)); } } } foreach (var constructorDetails in t.GetConstructors(ctorBindingFlags).Where(x => !x.ContainsGenericParameters)) { _logger.DebugFormat("Examining method {0}", constructorDetails.ToString()); var attr = InstrumentAttribute.GetEffectiveInstrumentationContext(constructorDetails.InstrumentationContext, typeLevelAttribute); if (attr != null) { toReturn.Add(GetInstrumentationTarget(constructorDetails, attr)); } } // Process nested types recursively, rather than enumerating them from the get-go so that we can apply // instrumentation scoping recursively too - the nested class will take on the instrumentation configuration // of the containing type, if any, or whatever's been passed down by initial settings foreach (var nested in t.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) { toReturn.AddRange(GetInstrumentationSet(nested, typeLevelAttribute)); } } else { _logger.DebugFormat("Skipping type {0} - generic types not supported", t.FullName); } return toReturn; }
protected virtual IEnumerable <InstrumentationTarget> GetInstrumentationSet(ITypeDetails t, InstrumentAttribute context) { var toReturn = new List <InstrumentationTarget>(); if (!t.IsGenericTypeDefinition) { // Does the type have an Instrument attribute? var typeLevelAttribute = t.InstrumentationContext; typeLevelAttribute = InstrumentAttribute.GetEffectiveInstrumentationContext(typeLevelAttribute, context); if (t.IsCompilerGenerated && (typeLevelAttribute == null || !typeLevelAttribute.IncludeCompilerGeneratedCode)) { // Bail out early - we've found a compiler-generated method and haven't been told to include 'em _logger.DebugFormat("Skipping type {0} - compiler-generated and configuration set to skip", t.FullName); return(toReturn); } _logger.DebugFormat("Processing type {0}", t.FullName); var baseBindingFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; var propBindingFlags = baseBindingFlags; var methodBindingFlags = baseBindingFlags; var ctorBindingFlags = baseBindingFlags; if (typeLevelAttribute == null) { propBindingFlags |= BindingFlags.NonPublic | BindingFlags.Public; methodBindingFlags |= BindingFlags.NonPublic | BindingFlags.Public; ctorBindingFlags |= BindingFlags.NonPublic | BindingFlags.Public; } else { if ((typeLevelAttribute.Scopes & InstrumentationScopes.PublicProperties) == InstrumentationScopes.PublicProperties) { propBindingFlags |= BindingFlags.Public; } if ((typeLevelAttribute.Scopes & InstrumentationScopes.NonPublicProperties) == InstrumentationScopes.NonPublicProperties) { propBindingFlags |= BindingFlags.NonPublic; } if ((typeLevelAttribute.Scopes & InstrumentationScopes.PublicMethods) == InstrumentationScopes.PublicMethods) { methodBindingFlags |= BindingFlags.Public; } if ((typeLevelAttribute.Scopes & InstrumentationScopes.NonPublicMethods) == InstrumentationScopes.NonPublicMethods) { methodBindingFlags |= BindingFlags.NonPublic; } if ((typeLevelAttribute.Scopes & InstrumentationScopes.PublicConstructors) == InstrumentationScopes.PublicConstructors) { ctorBindingFlags |= BindingFlags.Public; } if ((typeLevelAttribute.Scopes & InstrumentationScopes.NonPublicConstructors) == InstrumentationScopes.NonPublicConstructors) { ctorBindingFlags |= BindingFlags.NonPublic; } } _logger.DebugFormat("Prop flags {0}, Ctor flags {1}, Method flags {2}", propBindingFlags, ctorBindingFlags, methodBindingFlags); // Instrument everything in this type, irrespective of its member-level // details foreach (var methodDetails in t.GetMethods(methodBindingFlags)) { _logger.DebugFormat("Examining method {0}", methodDetails.ToString()); var attr = InstrumentAttribute.GetEffectiveInstrumentationContext(methodDetails.InstrumentationContext, typeLevelAttribute); if (attr != null && (!methodDetails.IsCompilerGenerated || attr.IncludeCompilerGeneratedCode)) { toReturn.Add(GetInstrumentationTarget(methodDetails, attr)); } } foreach (var propertyDetails in t.GetProperties(propBindingFlags)) { _logger.DebugFormat("Examining property {0}.{1}", t.FullName, propertyDetails.Name); var getMethod = propertyDetails.GetMethod; var setMethod = propertyDetails.SetMethod; if (getMethod != null && getMethod.ContainsGenericParameters) { getMethod = null; } if (setMethod != null && setMethod.ContainsGenericParameters) { setMethod = null; } if (getMethod != null) { var getMethodAttr = InstrumentAttribute.GetEffectiveInstrumentationContext(propertyDetails.InstrumentationContext, getMethod.InstrumentationContext, typeLevelAttribute); if (getMethodAttr != null) { toReturn.Add(GetInstrumentationTarget(getMethod, getMethodAttr)); } } if (setMethod != null) { var setMethodAttr = InstrumentAttribute.GetEffectiveInstrumentationContext(propertyDetails.InstrumentationContext, setMethod.InstrumentationContext, typeLevelAttribute); if (setMethodAttr != null) { toReturn.Add(GetInstrumentationTarget(setMethod, setMethodAttr)); } } } foreach (var constructorDetails in t.GetConstructors(ctorBindingFlags).Where(x => !x.ContainsGenericParameters)) { _logger.DebugFormat("Examining method {0}", constructorDetails.ToString()); var attr = InstrumentAttribute.GetEffectiveInstrumentationContext(constructorDetails.InstrumentationContext, typeLevelAttribute); if (attr != null) { toReturn.Add(GetInstrumentationTarget(constructorDetails, attr)); } } // Process nested types recursively, rather than enumerating them from the get-go so that we can apply // instrumentation scoping recursively too - the nested class will take on the instrumentation configuration // of the containing type, if any, or whatever's been passed down by initial settings foreach (var nested in t.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) { toReturn.AddRange(GetInstrumentationSet(nested, typeLevelAttribute)); } } else { _logger.DebugFormat("Skipping type {0} - generic types not supported", t.FullName); } return(toReturn); }