Beispiel #1
0
        public static MethodReference GetCacheGetterMethod(ClassWeavingContext classWeavingContext)
        {
            if (classWeavingContext == null)
            {
                throw new ArgumentNullException(nameof(classWeavingContext));
            }

            // TODO: Check if this can be inherited, extract to class level
            List <PropertyDefinition> propertyDefinitions =
                classWeavingContext.TypeDefinition.TryGetCacheGetterProperty(classWeavingContext.References);

            // TODO: Also check fields
            if (propertyDefinitions == null || propertyDefinitions.Count != 1)
            {
                throw new WeavingException("Cache Property not found or multiple properties found.");
            }

            MethodReference methodDefinition = classWeavingContext.TypeDefinition.Module.ImportReference(propertyDefinitions.Single().GetMethod);

            if (methodDefinition.DeclaringType.GenericParameters.Any())
            {
                return(methodDefinition.MakeHostInstanceGeneric(methodDefinition.DeclaringType.GenericParameters.Cast <TypeReference>()
                                                                .ToArray()));
            }

            return(methodDefinition);
        }
        public override void Execute()
        {
            References references = Fody.References.Init(this);

            foreach (WeavingCandidate weavingCandidate in ModuleDefinition.GetWeavingCandidates(references))
            {
                if (weavingCandidate.ClassDefinition.HasCacheAttribute(references) && !weavingCandidate.MethodDefinitions
                    .Where(x => !x.HasNoCacheAttribute(references))
                    .Any(x => x.IsEligibleForWeaving(references)))
                {
                    WriteWarning(
                        $"Class {weavingCandidate.ClassDefinition.Resolve().FullName} contains [Cache] attribute but does not contain eligible methods for caching");
                    continue;
                }

                if (!weavingCandidate.ClassDefinition.IsEligibleForWeaving(references))
                {
                    WriteWarning(
                        $"Class {weavingCandidate.ClassDefinition.Name} contains [Cache] attribute but does not contain a single property implementing IMemoryCache interface");
                    continue;
                }

                ClassWeavingContext classWeavingContext = new ClassWeavingContext(weavingCandidate.ClassDefinition, references);
                classWeavingContext.CacheGetterMethod = MemoryCache.GetCacheGetterMethod(classWeavingContext);

                foreach (MethodDefinition methodDefinition in weavingCandidate.MethodDefinitions)
                {
                    if (!methodDefinition.IsEligibleForWeaving(references))
                    {
                        // Show warning if test was marked explicitly
                        if (methodDefinition.HasCacheAttribute(references))
                        {
                            WriteWarning($"Method {methodDefinition.FullName} contains [Cache] attribute but is not eligible for weaving");
                            break;
                        }

                        continue;
                    }

                    if (methodDefinition.HasNoCacheAttribute(references))
                    {
                        continue;
                    }

                    MethodWeavingContext methodWeavingContext = new MethodWeavingContext(classWeavingContext, methodDefinition);

                    MemoryCache.AddMethodVariables(methodWeavingContext);
                    ILProcessorContext processorContext = MemoryCache.WeaveCreateKey(methodWeavingContext);
                    MemoryCache.WeaveTryGetValueAndReturn(methodWeavingContext, processorContext);
                    MemoryCache.WeaveSetBeforeReturns(methodWeavingContext);
                }
            }
        }
        public static MethodReference GetCacheGetterMethod(ClassWeavingContext classWeavingContext)
        {
            if (classWeavingContext == null)
            {
                throw new ArgumentNullException(nameof(classWeavingContext));
            }

            // TODO: Check if this can be inherited, extract to class level
            List <PropertyDefinition> propertyDefinitions = classWeavingContext.TypeDefinition.Properties.Where(definition =>
            {
                TypeDefinition typeDefinition       = definition.PropertyType.Resolve();
                TypeDefinition memoryCacheInterface = classWeavingContext.References.MemoryCacheInterface.Resolve();

                if (definition.GetMethod.IsStatic)
                {
                    return(false);
                }

                if (typeDefinition.IsInterface && typeDefinition.Equals(memoryCacheInterface))
                {
                    return(true);
                }

                if (typeDefinition.Interfaces.Any(x => x.InterfaceType == memoryCacheInterface))
                {
                    return(true);
                }

                return(false);
            })
                                                            .ToList();

            // TODO: Also check fields
            if (propertyDefinitions.Count != 1)
            {
                throw new WeavingException("Property not found");
            }

            MethodDefinition methodDefinition = propertyDefinitions.Single().GetMethod;

            if (methodDefinition.DeclaringType.GenericParameters.Any())
            {
                return(methodDefinition.MakeHostInstanceGeneric(methodDefinition.DeclaringType.GenericParameters.Cast <TypeReference>()
                                                                .ToArray()));
            }

            return(methodDefinition);
        }
        public override void Execute()
        {
            References references = Fody.References.Init(this);

            // TODO: Extract to method
            var elementsToCache = ModuleDefinition.Types.Select(type =>
            {
                if (type.HasCacheAttribute(references))
                {
                    return(new { Type = type, Methods = type.Methods.ToList() });
                }

                return(new { Type = type, Methods = type.Methods.Where(method => method.HasCacheAttribute(references)).ToList(), });
            })
                                  .Where(x => x.Methods.Any())
                                  .ToList();

            foreach (var elementToCache in elementsToCache)
            {
                if (!elementToCache.Type.IsEligibleForWeaving(references))
                {
                    // TODO: Create warning
                    continue;
                }

                ClassWeavingContext classWeavingContext = new ClassWeavingContext(elementToCache.Type, references);
                classWeavingContext.CacheGetterMethod = MemoryCache.GetCacheGetterMethod(classWeavingContext);

                foreach (MethodDefinition methodDefinition in elementToCache.Methods)
                {
                    if (!methodDefinition.IsEligibleForWeaving(references))
                    {
                        // TODO: Create warning if marked explicit for weaving
                        continue;
                    }

                    MethodWeavingContext methodWeavingContext = new MethodWeavingContext(classWeavingContext, methodDefinition);

                    MemoryCache.AddMethodVariables(methodWeavingContext);
                    ILProcessorContext processorContext = MemoryCache.WeaveCreateKey(methodWeavingContext);
                    MemoryCache.WeaveTryGetValueAndReturn(methodWeavingContext, processorContext);
                    MemoryCache.WeaveSetBeforeReturns(methodWeavingContext);
                }
            }
        }
 public MethodWeavingContext(ClassWeavingContext classWeavingContext, MethodDefinition methodDefinition)
 {
     ClassWeavingContext = classWeavingContext;
     MethodDefinition    = methodDefinition;
 }