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