public CacheProxyType(CacheAssembly assembly, CacheInterface @interface, FuncHelper helper, IReadOnlyDictionary <string, MethodInfo> cacheHelperMethods) : base(assembly) { _interface = @interface; _helper = helper; _cacheHelperMethods = cacheHelperMethods; }
public CacheAssembly(string fileName, IEnumerable <string> searchDirectories, ILogger logger, bool readWrite, bool readSymbols = false) { var resolver = new DefaultAssemblyResolver(); foreach (var dir in searchDirectories) { logger.Message("Add search directory", dir); resolver.AddSearchDirectory(dir); } var parameter = new ReaderParameters { ReadWrite = readWrite, ReadSymbols = readSymbols, AssemblyResolver = resolver }; _logger = logger; _readSymbols = readSymbols; _assembly = AssemblyDefinition.ReadAssembly(fileName, parameter); _helper = new FuncHelper(_assembly.MainModule); MainModule = _assembly.MainModule; KnowTypes = MainModule .AssemblyReferences .Select(asm => ResolveAssemblyNameReference(resolver, asm)) .Where(item => item != null) .SelectMany(item => item !.GetTypes()) .ToArray(); _cacheHelperMethods = typeof(CacheHelper).GetMethods() .Where(m => m.DeclaringType == typeof(CacheHelper)) .GroupBy(m => m.Name) .ToDictionary(g => g.Key, g => ImportMethod(g.First())); }
private static void BuildFunc(CacheMethod method, ILGenerator il, Type keyType, Type valueType) { Type funcType; if (method.Method.IsAbstract) { Ldarg(il, method.Value + 1); funcType = method.Method.GetParameters()[method.Value].ParameterType; } else { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldftn, method.Method); var result = method.Method.GetParameters().Select(p => p.ParameterType).Union(new[] { valueType }).ToArray(); funcType = result.Length switch { 1 => typeof(Func <>).MakeGenericType(result), 2 => typeof(Func <,>).MakeGenericType(result), 3 => typeof(Func <, ,>).MakeGenericType(result), 4 => typeof(Func <, , ,>).MakeGenericType(result), _ => throw CacheTypeResolver.ParameterException(method.Method.DeclaringType, method.Method) }; il.Emit(OpCodes.Newobj, funcType.GetConstructors()[0]); } var args = funcType.GetGenericArguments(); Type?arg1 = null, arg2 = null, arg3 = null, returnArg = null; if (args.Length > 1) { arg1 = args[0] == keyType ? typeof(object) : args[0]; } if (args.Length > 2) { arg2 = args[1] == keyType ? typeof(object) : args[1]; } if (args.Length > 3) { arg3 = args[2] == keyType ? typeof(object) : args[2]; } if (args.Length > 4) { throw CacheTypeResolver.ParameterException(method.Method.DeclaringType, method.Method); } if (args[args.Length - 1].IsGenericType) { var type = args[args.Length - 1].GetGenericTypeDefinition(); if (type == typeof(Task <>) || type == typeof(ValueTask <>)) { returnArg = type; } } if (arg1 != typeof(object) || arg2 != typeof(TimeSpan) || arg3 != typeof(CancellationToken) || method.AsyncType != null && returnArg != typeof(ValueTask <>)) { il.Emit(OpCodes.Call, (method.AsyncType == null ? FuncHelper.GetWrapMethod(arg1, arg2, arg3, returnArg) : FuncHelper.GetWrapAsyncMethod(arg1, arg2, arg3, returnArg)) .MakeGenericMethod(keyType, method.ValueType)); } }