コード例 #1
0
        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));
            }
        }
コード例 #2
0
        public static Type CreateProxy(ModuleBuilder module, Type type)
        {
            if (module == null)
            {
                throw new ArgumentNullException(nameof(module));
            }
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            var tb = module.DefineType($"{type.FullName}@Proxy@{type.Assembly.GetHashCode()}", TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.NotPublic);

            var cacheType = CacheTypeResolver.Resolve(type);
            var fb        = MakeField(tb, cacheType);

            foreach (var method in cacheType.Methods)
            {
                var mb = tb.DefineMethod(method.Method.Name,
                                         type.IsInterface
                        ? MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot
                        : MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.HideBySig,
                                         method.Method.ReturnType,
                                         method.Method.GetParameters().Select(p => p.ParameterType).ToArray());
                var il = mb.GetILGenerator();

                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, fb);
                il.Emit(OpCodes.Ldarg_1);

                switch (method.Operation)
                {
                case CacheOperation.Get:
                    BuildGet(method, il, cacheType.DefaultTtl);
                    break;

                case CacheOperation.Set:
                    BuildSet(method, il, cacheType.DefaultTtl);
                    break;

                case CacheOperation.Remove:
                    BuildRemove(method, il);
                    break;

                default:
                    throw new InvalidOperationException($"{mb.Name}不支持的操作{method.Operation}");
                }

                il.Emit(OpCodes.Ret);

                if (type.IsInterface)
                {
                    tb.DefineMethodOverride(mb, method.Method);
                }
            }
#if NETSTANDARD2_0
            return(tb.CreateTypeInfo() !);
#else
            return(tb.CreateType() !);
#endif
        }
コード例 #3
0
        private Type CreateProxy(ModuleBuilder module, Type type)
        {
            if (module == null)
            {
                throw new ArgumentNullException(nameof(module));
            }
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            var proxyType = module.DefineType($"{type.FullName}@Proxy@{type.Assembly.GetHashCode()}", TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.NotPublic);
#endif
            var cacheType = CacheTypeResolver.Resolve(type);
            var filed     = proxyType.DefineField("_helper", typeof(CacheHelper), FieldAttributes.Private | FieldAttributes.InitOnly);

            BuildConstructors(proxyType, cacheType, filed);

            foreach (var method in cacheType.Methods)
            {
                var mb = proxyType.DefineMethod(method.Method.Name,
                                                type.IsInterface
                        ? MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot
                        : MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig,
                                                method.Method.ReturnType,
                                                method.Method.GetParameters().Select(p => p.ParameterType).ToArray());

                var il = mb.GetILGenerator();

                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, filed);
                il.Emit(OpCodes.Ldarg_1);

                DefineGenericParameters(mb, method.Method);

                switch (method.Operation)
                {
                case CacheOperation.Get:
                    BuildGet(method, il, cacheType.DefaultTtl);
                    break;

                case CacheOperation.Set:
                    BuildSet(method, il, cacheType.DefaultTtl);
                    break;

                case CacheOperation.Remove:
                    BuildRemove(method, il);
                    break;

                default:
                    throw new InvalidOperationException($"{mb.Name}不支持的操作{method.Operation}");
                }

                il.Emit(OpCodes.Ret);
#if !BuildTask
                if (type.IsInterface)
                {
                    proxyType.DefineMethodOverride(mb, method.Method);
                }
#endif
                BuildParameters(mb.DefineParameter, method.Method.GetParameters());
            }
#if BuildTask
            return(proxyType);
#elif NETSTANDARD2_0
            return(proxyType.CreateTypeInfo() !);
#else
            return(proxyType.CreateType() !);
#endif
        }