private bool ShouldWeaveProperty(PropertyDefinition property) { CustomAttribute classLevelCacheAttribute = property.DeclaringType.CustomAttributes.SingleOrDefault(x => x.Constructor.DeclaringType.Name == CacheAttributeName); bool hasClassLevelCache = classLevelCacheAttribute != null; bool hasPropertyLevelCache = property.ContainsAttribute(CacheAttributeName); bool hasNoCacheAttribute = property.ContainsAttribute(NoCacheAttributeName); bool isCacheGetter = property.Name == CacheGetterName; bool hasGetAccessor = property.GetMethod != null; bool hasSetAccessor = property.GetMethod != null; bool isAutoProperty = hasGetAccessor && hasSetAccessor && property.GetMethod.ContainsAttribute(ModuleDefinition.ImportType<CompilerGeneratedAttribute>()) && property.SetMethod.ContainsAttribute(ModuleDefinition.ImportType<CompilerGeneratedAttribute>()); if (hasNoCacheAttribute || isCacheGetter || isAutoProperty || !hasGetAccessor) { // Never weave Cache property, auto-properties, write-only properties and properties explicitly excluded return false; } if (hasPropertyLevelCache) { // Always weave properties explicitly marked for cache return true; } if (hasClassLevelCache && !CacheAttributeExcludesProperties(classLevelCacheAttribute)) { // Otherwise weave if marked at class level return PropertyCacheEnabledByDefault || CacheAttributeMembersExplicitly(classLevelCacheAttribute, Members.Properties); } return false; }