public MyTest(IEmit instance, IInterceptor interceptor) { this.instance = instance; this.interceptor = interceptor; }
static void Main(string[] args) { var assemblyName = new AssemblyName("CodeArts.Emit"); var assemblyBuilder = AppDomain.CurrentDomain .DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); var moduleBuilder = assemblyBuilder.DefineDynamicModule("CodeArts.Module", "CodeArts.Emit.dll"); var iEmitType = typeof(IEmit); var interceptorType = typeof(IInterceptor); var typeBuilder = moduleBuilder.DefineType("EmitProxy", TypeAttributes.Class | TypeAttributes.NotPublic, null, new Type[] { iEmitType }); var instanceField = typeBuilder.DefineField("instance", iEmitType, FieldAttributes.Private | FieldAttributes.InitOnly); var interceptorField = typeBuilder.DefineField("interceptor", interceptorType, FieldAttributes.Private | FieldAttributes.InitOnly); var constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { iEmitType, interceptorType }); constructorBuilder.DefineParameter(1, ParameterAttributes.None, "instance"); constructorBuilder.DefineParameter(2, ParameterAttributes.None, "interceptor"); var ilOfCtor = constructorBuilder.GetILGenerator(); var objectType = typeof(object); ilOfCtor.Emit(OpCodes.Ldarg_0); ilOfCtor.Emit(OpCodes.Call, objectType.GetConstructor(new Type[0])); ilOfCtor.Emit(OpCodes.Ldarg_0); ilOfCtor.Emit(OpCodes.Ldarg_1); ilOfCtor.Emit(OpCodes.Stfld, instanceField); ilOfCtor.Emit(OpCodes.Ldarg_0); ilOfCtor.Emit(OpCodes.Ldarg_2); ilOfCtor.Emit(OpCodes.Stfld, interceptorField); ilOfCtor.Emit(OpCodes.Ret); var constructorStaticBuilder = typeBuilder.DefineConstructor(MethodAttributes.Static, CallingConventions.Standard, Type.EmptyTypes); var ilOfStaticCtor = constructorStaticBuilder.GetILGenerator(); var invokeType = typeof(InvokeBinder); var returnValue = typeof(IIntercept).GetProperty("ReturnValue"); var invokeCtor = invokeType.GetConstructor(new Type[] { typeof(object), typeof(MethodInfo), typeof(object[]) }); var interceptMethod = interceptorType.GetMethod("Intercept", new Type[] { typeof(IIntercept) }); foreach (var method in iEmitType.GetMethods()) { var parameters = method.GetParameters(); var parameterTypes = parameters.Select(x => x.ParameterType).ToArray(); var methodBuilder = typeBuilder.DefineMethod(method.Name, MethodAttributes.Public | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final, CallingConventions.Standard); if (method.IsGenericMethod) { var genericArguments = method.GetGenericArguments(); var newGenericParameters = methodBuilder.DefineGenericParameters(genericArguments.Select(x => x.Name).ToArray()); foreach (var item in genericArguments.Zip(newGenericParameters, (g, t) => { t.SetGenericParameterAttributes(g.GenericParameterAttributes); t.SetInterfaceConstraints(g.GetGenericParameterConstraints()); t.SetBaseTypeConstraint(g.BaseType); return(true); })) { } } methodBuilder.SetReturnType(method.ReturnType); methodBuilder.SetParameters(parameterTypes); parameters.ForEach((p, index) => { methodBuilder.DefineParameter(index + 1, p.Attributes, p.Name); }); var ilGen = methodBuilder.GetILGenerator(); LocalBuilder local = method.IsGenericMethod ? CreateInvokeBinder(typeBuilder, ilOfStaticCtor, ilGen, instanceField, invokeCtor, method.MakeGenericMethod(methodBuilder.GetGenericArguments()), parameterTypes) : CreateInvokeBinder(typeBuilder, ilOfStaticCtor, ilGen, instanceField, invokeCtor, method, parameterTypes); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldfld, interceptorField); ilGen.Emit(OpCodes.Ldloc, local); ilGen.Emit(OpCodes.Call, interceptMethod); if (method.ReturnType == typeof(void)) { ilGen.Emit(OpCodes.Pop); } else { ilGen.Emit(OpCodes.Callvirt, returnValue.GetMethod); if (method.ReturnType.IsValueType && !(method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Nullable <>))) { var value = ilGen.DeclareLocal(typeof(object)); ilGen.Emit(OpCodes.Stloc, value); ilGen.Emit(OpCodes.Ldloc, value); var nullLabel = ilGen.DefineLabel(); ilGen.Emit(OpCodes.Ldnull); ilGen.Emit(OpCodes.Ceq); ilGen.Emit(OpCodes.Brfalse_S, nullLabel); ilGen.Emit(OpCodes.Nop); ilGen.Emit(OpCodes.Ldstr, "Interceptors failed to set a return value, or swallowed the exception thrown by the target."); ilGen.Emit(OpCodes.Newobj, typeof(InvalidOperationException).GetConstructor(new Type[] { typeof(string) })); ilGen.Emit(OpCodes.Throw); ilGen.MarkLabel(nullLabel); ilGen.Emit(OpCodes.Ldloc, value); } if (method.ReturnType.IsValueType || method.ReturnType.IsGenericParameter) { ilGen.Emit(OpCodes.Unbox_Any, method.ReturnType); } else { ilGen.Emit(OpCodes.Castclass, method.ReturnType); } } ilGen.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodBuilder, method); } ilOfStaticCtor.Emit(OpCodes.Ret); var type = typeBuilder.CreateType(); assemblyBuilder.Save("CodeArts.Emit.dll"); IEmit emit = (IEmit)Activator.CreateInstance(type, new Emit(), new Interceptor()); emit.Test(); var g1 = emit.TestG(new object()); var g2 = emit.TestG(18); var g3 = emit.TestGConstraint(DateTimeKind.Utc); var i = emit.TestInt32(8); var v = emit.TestValueType(1); var c = emit.TestClas(); }