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); }
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); }
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))); }
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); }
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); }
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(); }
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(); }