Exemple #1
0
 public CacheProxyType(CacheAssembly assembly, CacheInterface @interface, FuncHelper helper, IReadOnlyDictionary <string, MethodInfo> cacheHelperMethods)
     : base(assembly)
 {
     _interface          = @interface;
     _helper             = helper;
     _cacheHelperMethods = cacheHelperMethods;
 }
Exemple #2
0
        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));
            }
        }