public static MethodBuilder CreateDelegateImplementation(TypeBuilder typeBuilder, FieldBuilder targetField, MethodInfo mi) { MethodBuilder methodBuilder = typeBuilder.DefineMethod(mi.Name, MethodAttributes.Public | MethodAttributes.Virtual, mi.ReturnType, mi.GetParameters().Select(param => param.ParameterType).ToArray()); ILGenerator il = methodBuilder.GetILGenerator(); #region forwarding implementation LocalBuilder baseReturn = null; if (mi.ReturnType != typeof(void)) { baseReturn = il.DeclareLocal(mi.ReturnType); } // Call the target method il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, targetField); // Load the call parameters for (int i = 0; i < mi.GetParameters().Length; i++) { CodeGenUtil.EmitLoadArgument(il, i); } // Make the call MethodInfo callTarget = targetField.FieldType.GetMethod(mi.Name, mi.GetParameters().Select(pi => pi.ParameterType).ToArray()); il.Emit(OpCodes.Callvirt, callTarget); if (mi.ReturnType != typeof(void)) { il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldloc_0); } il.Emit(OpCodes.Ret); #endregion return(methodBuilder); }
static DuckTypingProxyFactory() { _assemblyBuilder = CodeGenUtil.CreateAssemblyBuilder(_assemblyName); _moduleBuilder = CodeGenUtil.CreateModuleBuilder(_assemblyBuilder, _assemblyName); }
public Type GenerateProxyType(Type typeOfIMyDuck, Type typeOfOtherDuck) { TypeAttributes newAttributes = TypeAttributes.Public | TypeAttributes.Class; TypeBuilder typeBuilder = _moduleBuilder.DefineType( typeOfOtherDuck.Name + "_DuckTypingProxy" + Guid.NewGuid().ToString(), newAttributes); // Add interface implementation typeBuilder.AddInterfaceImplementation(typeOfIMyDuck); FieldBuilder targetField = typeBuilder.DefineField("target", typeOfOtherDuck, FieldAttributes.Private); foreach (MethodInfo mi in typeOfIMyDuck.GetMethods()) { CodeGenUtil.CreateDelegateImplementation(typeBuilder, targetField, mi); } foreach (PropertyInfo pi in typeOfIMyDuck.GetProperties()) { PropertyBuilder pb = typeBuilder.DefineProperty( pi.Name, pi.Attributes, pi.PropertyType, pi.GetIndexParameters().Select(param => param.ParameterType).ToArray() ); MethodInfo getMi = pi.GetGetMethod(); if (getMi != null) { MethodBuilder getMethod = CodeGenUtil.CreateDelegateImplementation(typeBuilder, targetField, getMi); pb.SetGetMethod(getMethod); } MethodInfo setMi = pi.GetSetMethod(); if (setMi != null) { MethodBuilder setMethod = CodeGenUtil.CreateDelegateImplementation(typeBuilder, targetField, setMi); pb.SetSetMethod(setMethod); } } //Constructor ConstructorBuilder ctorBuilder = typeBuilder.DefineConstructor( MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.HasThis, new Type[] { typeOfOtherDuck }); ctorBuilder.DefineParameter(1, ParameterAttributes.None, "target"); ILGenerator il = ctorBuilder.GetILGenerator(); // Call base class constructor il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, CodeGenUtil.GetConstructorInfo(() => new object())); // Initialize the target field il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Stfld, targetField); il.Emit(OpCodes.Ret); Type result = typeBuilder.CreateType(); #if DEBUG _assemblyBuilder.Save(_assemblyName + ".dll"); #endif return(result); }