Example #1
0
        private static bool CheckCacheTypeMethods(BaseModuleWeaver weaver, TypeDefinition cacheType)
        {
            weaver.LogInfo(string.Format("Checking CacheType methods ({0}, {1}, {2}).", CacheTypeContainsMethodName,
                                         CacheTypeStoreMethodName, CacheTypeRetrieveMethodName));

            if (CacheTypeGetContainsMethod(cacheType, CacheTypeContainsMethodName) == null)
            {
                weaver.LogWarning(string.Format("Method {0} missing in {1}.", CacheTypeContainsMethodName, cacheType.FullName));

                return(false);
            }

            if (CacheTypeGetStoreMethod(cacheType, CacheTypeStoreMethodName) == null)
            {
                weaver.LogWarning(string.Format("Method {0} missing in {1}.", CacheTypeStoreMethodName, cacheType.FullName));

                return(false);
            }

            if (CacheTypeGetRetrieveMethod(cacheType, CacheTypeRetrieveMethodName) == null)
            {
                weaver.LogWarning(string.Format("Method {0} missing in {1}.", CacheTypeRetrieveMethodName, cacheType.FullName));

                return(false);
            }

            weaver.LogInfo(string.Format("CacheInterface methods found."));

            return(true);
        }
Example #2
0
        public static bool IsMethodValidForWeaving(BaseModuleWeaver weaver, MethodDefinition propertyGet, MethodDefinition methodDefinition)
        {
            //only non-static method need a getter
            if (propertyGet == null && !methodDefinition.IsStatic)
            {
                weaver.LogWarning(string.Format("Class {0} does not contain or inherit Getter {1}. Skip weaving of method {2}.",
                                                methodDefinition.DeclaringType.Name, CacheGetterName, methodDefinition.Name));

                return(false);
            }

            //not need anymore
            //if (methodDefinition.IsStatic && !propertyGet.IsStatic)
            //{
            //    weaver.LogWarning(string.Format("Method {2} of Class {0} is static, Getter {1} is not. Skip weaving of method {2}.",
            //        methodDefinition.DeclaringType.Name, CacheGetterName, methodDefinition.Name));

            //    return false;
            //}

            if (!methodDefinition.IsStatic && !CheckCacheTypeMethods(weaver, propertyGet.ReturnType.Resolve()))
            {
                weaver.LogWarning(
                    string.Format(
                        "ReturnType {0} of Getter {1} of Class {2} does not implement all methods. Skip weaving of method {3}.",
                        propertyGet.ReturnType.Name, CacheGetterName, methodDefinition.DeclaringType.Name, methodDefinition.Name));

                return(false);
            }

            return(true);
        }
Example #3
0
        public bool Validate(BaseModuleWeaver weaver)
        {
            if (!Effects.Any())
            {
                weaver.LogWarning($"Type {Host.FullName} has defined as an aspect, but lacks any effect.");
            }

            if (Host.HasGenericParameters)
            {
                weaver.LogError($"Aspect {Host.FullName} should not have generic parameters.");
                return(false);
            }

            if (Host.IsAbstract)
            {
                weaver.LogError($"Aspect {Host.FullName} cannot be static nor abstract.");
                return(false);
            }

            if (GetFactoryMethod() == null)
            {
                if (Factory != null)
                {
                    weaver.LogError($"Type {Factory.FullName} should have 'public static object GetInstance(Type)' method in order to be aspect factory.");
                }
                else
                {
                    weaver.LogError($"Aspect {Host.FullName} has no parameterless public constructor nor valid factory.");
                }
                return(false);
            }

            return(Effects.All(e => e.Validate(this, weaver)));
        }
Example #4
0
        private static bool IsPropertySetterValidForWeaving(BaseModuleWeaver weaver, MethodDefinition propertyGet, MethodDefinition methodDefinition)
        {
            if (!IsMethodValidForWeaving(weaver, propertyGet, methodDefinition))
            {
                return(false);
            }

            if (CacheTypeGetRemoveMethod(propertyGet.ReturnType.Resolve(), CacheTypeRemoveMethodName) == null)
            {
                weaver.LogWarning(string.Format("Method {0} missing in {1}.", CacheTypeRemoveMethodName,
                                                propertyGet.ReturnType.Resolve().FullName));

                weaver.LogWarning(
                    string.Format(
                        "ReturnType {0} of Getter {1} of Class {2} does not implement all methods. Skip weaving of method {3}.",
                        propertyGet.ReturnType.Name, CacheGetterName, methodDefinition.DeclaringType.Name, methodDefinition.Name));

                return(false);
            }

            return(true);
        }
Example #5
0
        public static void WeaveMethod(BaseModuleWeaver weaver, MethodDefinition methodDefinition, CustomAttribute attribute)
        {
            MethodDefinition propertyGet = GetCacheGetter(methodDefinition);

            if (!IsMethodValidForWeaving(weaver, propertyGet, methodDefinition))
            {
                return;
            }

            if (methodDefinition.ReturnType == methodDefinition.Module.TypeSystem.Void)
            {
                weaver.LogWarning(string.Format("Method {0} returns void. Skip weaving of method {0}.", methodDefinition.Name));

                return;
            }

            weaver.LogInfo(string.Format("Weaving method {0}::{1}.", methodDefinition.DeclaringType.Name, methodDefinition.Name));

            WeaveMethod(weaver, methodDefinition, attribute, propertyGet);
        }
Example #6
0
 protected virtual void LoadTargetArgument(PointCut pc, AdviceArgument parameter)
 {
     _weaver.LogWarning($"Advice {_effect.Type.ToString()} does not support {parameter.Source.ToString()} argument and will always return null");
     pc.Null();
 }
Example #7
0
        public static void WeaveMethod(BaseModuleWeaver weaver, MethodDefinition methodDefinition, CustomAttribute attribute, MethodReference propertyGet)
        {
            //try to add propert
            PropertyDefinition propertyInject = null;

            if (propertyGet == null && methodDefinition.IsStatic && !methodDefinition.DeclaringType.Properties.Any(p => p.Name == "Cache"))
            {
                propertyInject = InjectProperty(weaver, methodDefinition);
                propertyGet    = propertyInject.GetMethod;
            }

            if (propertyInject == null)
            {
                propertyInject = methodDefinition.DeclaringType.Properties.FirstOrDefault(p => p.Name == "Cache");
            }

            //weave mthod
            methodDefinition.Body.InitLocals = true;

            methodDefinition.Body.SimplifyMacros();

            if (propertyGet.DeclaringType.HasGenericParameters)
            {
                propertyGet = propertyGet.MakeHostInstanceGeneric(propertyGet.DeclaringType.GenericParameters.Cast <TypeReference>().ToArray());
            }

            Instruction firstInstruction = methodDefinition.Body.Instructions.First();

            ICollection <Instruction> returnInstructions =
                methodDefinition.Body.Instructions.ToList().Where(x => x.OpCode == OpCodes.Ret).ToList();

            if (returnInstructions.Count == 0)
            {
                weaver.LogWarning(string.Format("Method {0} does not contain any return statement. Skip weaving of method {0}.",
                                                methodDefinition.Name));
                return;
            }

            // Add local variables
            int cacheKeyIndex    = methodDefinition.AddVariable(weaver.ModuleDefinition.TypeSystem.String);
            int resultIndex      = methodDefinition.AddVariable(methodDefinition.ReturnType);
            int objectArrayIndex = methodDefinition.AddVariable(weaver.ModuleDefinition.TypeSystem.Object.MakeArrayType());

            ILProcessor processor = methodDefinition.Body.GetILProcessor();

            // Generate CacheKeyTemplate
            string cacheKey = CreateCacheKeyString(methodDefinition);

            Instruction current = firstInstruction.Prepend(processor.Create(OpCodes.Ldstr, cacheKey), processor);

            current = SetCacheKeyLocalVariable(weaver, current, methodDefinition, processor, cacheKeyIndex, objectArrayIndex);

            //init CacheProvider when static method called
            if (methodDefinition.IsStatic)
            {
                var refModule      = ReferenceFinder.CacheAssembly.MainModule;
                var refProvider    = refModule.GetType("Cache.CacheProvider");
                var refProviderGet = refProvider.Method("get_Provider");
                var refSetter      = propertyInject.SetMethod;
                current = current.Append(processor.Create(OpCodes.Call, methodDefinition.Module.ImportReference(refProviderGet)), processor);
                current = current.Append(processor.Create(OpCodes.Call, methodDefinition.Module.ImportReference(refSetter)), processor);
            }

            current = InjectCacheKeyCreatedCode(weaver, methodDefinition, current, processor, cacheKeyIndex);

            TypeDefinition propertyGetReturnTypeDefinition = propertyGet.ReturnType.Resolve();

            if (!propertyGet.Resolve().IsStatic)
            {
                current = current.AppendLdarg(processor, 0);
            }

            MethodReference methodReferenceContain =
                methodDefinition.Module.ImportMethod(CacheTypeGetContainsMethod(propertyGetReturnTypeDefinition,
                                                                                CacheTypeContainsMethodName));

            current = current
                      .Append(processor.Create(OpCodes.Call, methodDefinition.Module.ImportReference(propertyGet)), processor)
                      .AppendLdloc(processor, cacheKeyIndex)
                      .Append(processor.Create(OpCodes.Callvirt, methodReferenceContain), processor)
                      .Append(processor.Create(OpCodes.Brfalse, firstInstruction), processor);

            // False branche (store value in cache of each return instruction)
            foreach (Instruction returnInstruction in returnInstructions)
            {
                returnInstruction.Previous.AppendStloc(processor, resultIndex);


                AppendDebugWrite(weaver, returnInstruction.Previous, processor, "Storing to cache.");


                if (!propertyGet.Resolve().IsStatic)
                {
                    returnInstruction.Previous.AppendLdarg(processor, 0);
                }

                MethodReference methodReferenceStore =
                    methodDefinition.Module.ImportMethod(CacheTypeGetStoreMethod(propertyGetReturnTypeDefinition, CacheTypeStoreMethodName));

                returnInstruction.Previous
                .Append(processor.Create(OpCodes.Call, methodDefinition.Module.ImportReference(propertyGet)), processor)
                .AppendLdloc(processor, cacheKeyIndex)
                .AppendLdloc(processor, resultIndex)
                .AppendBoxIfNecessary(processor, methodDefinition.ReturnType);

                // Pass parameters to Store method if supported
                if (methodReferenceStore.Parameters.Count == 3)
                {
                    returnInstruction.Previous
                    .Append(processor.Create(OpCodes.Newobj,
                                             methodDefinition.Module.ImportReference(ReferenceFinder.DictionaryConstructor)), processor);

                    foreach (CustomAttributeNamedArgument property in attribute.Properties.Union(attribute.Fields))
                    {
                        returnInstruction.Previous
                        .AppendDup(processor)
                        .AppendLdstr(processor, property.Name)
                        .AppendLd(processor, property.Argument)
                        .AppendBoxIfNecessary(processor,
                                              property.Argument.Type != weaver.ModuleDefinition.TypeSystem.Object
                                    ? property.Argument.Type : ((CustomAttributeArgument)property.Argument.Value).Type)
                        .Append(processor.Create(OpCodes.Callvirt, methodDefinition.Module.ImportReference(ReferenceFinder.DictionaryAddMethod)),
                                processor);
                    }
                }

                returnInstruction.Previous
                .Append(processor.Create(OpCodes.Callvirt, methodReferenceStore), processor)
                .AppendLdloc(processor, resultIndex);
            }


            current = AppendDebugWrite(weaver, current, processor, "Loading from cache.");


            if (!propertyGet.Resolve().IsStatic)
            {
                current = current.AppendLdarg(processor, 0);
            }

            // Start of branche true
            MethodReference methodReferenceRetrieve =
                methodDefinition.Module.ImportMethod(CacheTypeGetRetrieveMethod(propertyGetReturnTypeDefinition,
                                                                                CacheTypeRetrieveMethodName)).MakeGeneric(new[] { methodDefinition.ReturnType });

            current.Append(processor.Create(OpCodes.Call, methodDefinition.Module.ImportReference(propertyGet)), processor)
            .AppendLdloc(processor, cacheKeyIndex)
            .Append(processor.Create(OpCodes.Callvirt, methodReferenceRetrieve), processor)
            .AppendStloc(processor, resultIndex)
            .Append(processor.Create(OpCodes.Br, returnInstructions.Last().Previous), processor);

            methodDefinition.Body.OptimizeMacros();
        }