public static void WeaveTryGetValueAndReturn(MethodWeavingContext methodWeavingContext, ILProcessorContext processorContext) { if (methodWeavingContext == null) { throw new ArgumentNullException(nameof(methodWeavingContext)); } if (processorContext == null) { throw new ArgumentNullException(nameof(processorContext)); } processorContext = processorContext.Append(x => x.Create(OpCodes.Ldarg_0)) .Append(x => x.Create(OpCodes.Call, methodWeavingContext.ClassWeavingContext.CacheGetterMethod)) .Append(x => x.Create(OpCodes.Ldloc, methodWeavingContext.CacheKeyVariableIndex.Value)) .Append(x => x.Create(OpCodes.Ldloca, methodWeavingContext.ResultVariableIndex.Value)) .Append(x => x.Create(OpCodes.Call, methodWeavingContext.ClassWeavingContext.References.GetTryGetValue(methodWeavingContext.MethodDefinition.ReturnType))); Instruction instructionNext = processorContext.CurrentInstruction.Next; processorContext.Append(x => x.Create(OpCodes.Brfalse, instructionNext)) .Append(x => x.Create(OpCodes.Ldloc, methodWeavingContext.ResultVariableIndex.Value)) .Append(x => x.Create(OpCodes.Ret)); }
private static ILProcessorContext CreateTupleConstructorCalls(MethodWeavingContext methodWeavingContext, ILProcessorContext processorContext, GenericInstanceType tupleType) { if (methodWeavingContext == null) { throw new ArgumentNullException(nameof(methodWeavingContext)); } if (processorContext == null) { throw new ArgumentNullException(nameof(processorContext)); } if (tupleType == null) { throw new ArgumentNullException(nameof(tupleType)); } TypeReference[] typeReferences = tupleType.GenericArguments.Cast <TypeReference>().ToArray(); if (typeReferences.Length == 8) { processorContext = MemoryCache.CreateTupleConstructorCalls(methodWeavingContext, processorContext, (GenericInstanceType)typeReferences.Last()); } MethodReference tupleConstructor = methodWeavingContext.ClassWeavingContext.References.GetSystemTupleConstructor(typeReferences); return(processorContext.Append(x => x.Create(OpCodes.Newobj, tupleConstructor))); }
public static void WeaveSetBeforeReturns(MethodWeavingContext methodWeavingContext) { MethodBody methodDefinitionBody = methodWeavingContext.MethodDefinition.Body; List <Instruction> returns = methodDefinitionBody.Instructions.Where(x => x.OpCode == OpCodes.Ret).ToList(); ILProcessor processor = methodDefinitionBody.GetILProcessor(); // TODO: Skip "ret" created above foreach (Instruction returnInstruction in returns.Skip(1)) { ILProcessorContext processorContext = processor.Before(returnInstruction) .Append(x => x.Create(OpCodes.Stloc, methodWeavingContext.ResultVariableIndex.Value)); processorContext = processorContext.Append(x => x.Create(OpCodes.Ldarg_0)) .Append(x => x.Create(OpCodes.Call, methodWeavingContext.ClassWeavingContext.CacheGetterMethod)) .Append(x => x.Create(OpCodes.Ldloc, methodWeavingContext.CacheKeyVariableIndex.Value)) .Append(x => x.Create(OpCodes.Ldloc, methodWeavingContext.ResultVariableIndex.Value)) .Append(x => x.Create(OpCodes.Call, methodWeavingContext.ClassWeavingContext.References.GetGenericSetMethod(methodWeavingContext.MethodDefinition .ReturnType))); // Not necessary, just return the return value from .Set ////.Append(x => x.Create(OpCodes.Pop)) ////.Append(x => x.Create(OpCodes.Ldloc, index)); } }
public static ILProcessorContext WeaveCreateKey(MethodWeavingContext methodWeavingContext) { if (methodWeavingContext == null) { throw new ArgumentNullException(nameof(methodWeavingContext)); } ILProcessorContext processorContext = methodWeavingContext.MethodDefinition.Body.GetILProcessor().Start(); string methodName = MemoryCache.CreateCacheKeyMethodName(methodWeavingContext.MethodDefinition); processorContext = processorContext.Append(x => x.Create(OpCodes.Ldstr, methodName)); foreach (GenericParameter genericParameter in methodWeavingContext.ClassWeavingContext.TypeDefinition.GenericParameters) { processorContext = processorContext.Append(x => x.Create(OpCodes.Ldtoken, genericParameter)) .Append(x => x.Create(OpCodes.Call, methodWeavingContext.ClassWeavingContext.References.GetTypeFromHandleMethod)); } foreach (GenericParameter genericParameter in methodWeavingContext.MethodDefinition.GenericParameters) { processorContext = processorContext.Append(x => x.Create(OpCodes.Ldtoken, genericParameter)) .Append(x => x.Create(OpCodes.Call, methodWeavingContext.ClassWeavingContext.References.GetTypeFromHandleMethod)); } for (int i = 0; i < methodWeavingContext.MethodDefinition.Parameters.Count; i++) { int value = i; processorContext = processorContext.Append(x => x.Create(OpCodes.Ldarg, value + 1)); } return(MemoryCache .CreateTupleConstructorCalls(methodWeavingContext, processorContext, (GenericInstanceType)methodWeavingContext.CacheKeyType) .Append(x => x.Create(OpCodes.Stloc, methodWeavingContext.CacheKeyVariableIndex.Value))); }
public static void WeaveSetBeforeReturns(MethodWeavingContext methodWeavingContext) { if (methodWeavingContext == null) { throw new ArgumentNullException(nameof(methodWeavingContext)); } CustomAttribute cacheAttribute = methodWeavingContext.MethodDefinition.TryGetCacheAttribute(methodWeavingContext.ClassWeavingContext.References); if (cacheAttribute == null) { cacheAttribute = methodWeavingContext.ClassWeavingContext.TypeDefinition.TryGetCacheAttribute(methodWeavingContext.ClassWeavingContext .References); } MethodBody methodDefinitionBody = methodWeavingContext.MethodDefinition.Body; List <Instruction> returns = methodDefinitionBody.Instructions.Where(x => x.OpCode == OpCodes.Ret).ToList(); ILProcessor processor = methodDefinitionBody.GetILProcessor(); // TODO: Skip "ret" created above foreach (Instruction returnInstruction in returns.Skip(1)) { ILProcessorContext processorContext = processor.Before(returnInstruction) .Append(x => x.Create(OpCodes.Stloc, methodWeavingContext.ResultVariableIndex.Value)); processorContext = processorContext.Append(x => x.Create(OpCodes.Ldarg_0)) .Append(x => x.Create(OpCodes.Call, methodWeavingContext.ClassWeavingContext.CacheGetterMethod)) .Append(x => x.Create(OpCodes.Ldloc, methodWeavingContext.CacheKeyVariableIndex.Value)) .Append(x => x.Create(OpCodes.Ldloc, methodWeavingContext.ResultVariableIndex.Value)); if (cacheAttribute.Properties.Any()) { processorContext = processorContext.Append(x => x.Create(OpCodes.Newobj, methodWeavingContext.ClassWeavingContext.References.MemoryCacheEntryOptionsConstructor)); foreach (CustomAttributeNamedArgument customAttributeNamedArgument in cacheAttribute.Properties) { switch (customAttributeNamedArgument.Name) { case "AbsoluteExpirationRelativeToNow": processorContext = processorContext.Append(x => x.Create(OpCodes.Dup)) .Append(x => x.Create(OpCodes.Ldc_R8, (double)customAttributeNamedArgument.Argument.Value)) .Append(x => x.Create(OpCodes.Call, methodWeavingContext.ClassWeavingContext.References.TimeSpanFromSecondsMethod)) .Append(x => x.Create(OpCodes.Newobj, methodWeavingContext.ClassWeavingContext.References.NullableTimeSpanConstructor)) .Append(x => x.Create(OpCodes.Callvirt, methodWeavingContext.ClassWeavingContext.References.MemoryCacheEntryOptionsAbsoluteExpirationRelativeToNowSetter)); break; case "SlidingExpiration": processorContext = processorContext.Append(x => x.Create(OpCodes.Dup)) .Append(x => x.Create(OpCodes.Ldc_R8, (double)customAttributeNamedArgument.Argument.Value)) .Append(x => x.Create(OpCodes.Call, methodWeavingContext.ClassWeavingContext.References.TimeSpanFromSecondsMethod)) .Append(x => x.Create(OpCodes.Newobj, methodWeavingContext.ClassWeavingContext.References.NullableTimeSpanConstructor)) .Append(x => x.Create(OpCodes.Callvirt, methodWeavingContext.ClassWeavingContext.References.MemoryCacheEntryOptionsSlidingExpirationSetter)); break; case "Priority": processorContext = processorContext.Append(x => x.Create(OpCodes.Dup)) .Append(x => x.Create(OpCodes.Ldc_I4, (int)customAttributeNamedArgument.Argument.Value)) .Append(x => x.Create(OpCodes.Callvirt, methodWeavingContext.ClassWeavingContext.References.MemoryCacheEntryOptionsPrioritySetter)); break; } } processorContext = processorContext.Append(x => x.Create(OpCodes.Call, methodWeavingContext.ClassWeavingContext.References.GetGenericSetMethodWithMemoryCacheEntryOptions( methodWeavingContext.MethodDefinition.ReturnType))); } else { processorContext = processorContext.Append(x => x.Create(OpCodes.Call, methodWeavingContext.ClassWeavingContext.References.GetGenericSetMethod(methodWeavingContext.MethodDefinition .ReturnType))); } // Not necessary, just return the return value from .Set ////.Append(x => x.Create(OpCodes.Pop)) ////.Append(x => x.Create(OpCodes.Ldloc, index)); } }