static void ImplementInterface(Type interfaceType, TypeBuilder builder, FieldBuilder channel) { if (builder.FindInterfaces((t, o) => t == interfaceType, null).Length == 0) { builder.AddInterfaceImplementation(interfaceType); var parentInterfaces = interfaceType.GetInterfaces(); foreach (var _interface in parentInterfaces) { ImplementInterface(_interface, builder, channel); } IEnumerable <OperationDescription> operations = null; var intInfo = interfaceType.GetTypeInfo(); if (ContractDescription.IsContract(intInfo)) { operations = ContractDescription.ValidateContract(intInfo); } else { operations = interfaceType.GetMethods().Select(x => new OperationDescription(x)); } foreach (var operation in operations) { var mb = builder.DefineMethod( $"{interfaceType.Name}.{operation.Name}", MethodAttributes.Public | MethodAttributes.Virtual, operation.ReturnType, operation.ParameterTypes); var il = mb.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, channel); MethodInfo invoke = null; //implement the user interface if (operation.IsOperation) { if (operation.IsOneWay) { invoke = ImplementingType.GetMethod("SendOneWay"); } else if (operation.IsVoidTask) { invoke = ImplementingType.GetMethod("SendVoid"); } else { invoke = ImplementingType.GetMethod("SendReturn") .MakeGenericMethod(operation.ReturnType.GetGenericArguments() .First()); } il.Emit(OpCodes.Ldstr, mb.Name); il.Emit(OpCodes.Ldc_I4_S, operation.ParameterTypes.Length); il.Emit(OpCodes.Newarr, typeof(object)); for (byte x = 0; x < operation.ParameterTypes.Length; x++) { var xType = operation.ParameterTypes[x]; il.Emit(OpCodes.Dup); il.Emit(OpCodes.Ldc_I4_S, x); switch (x) { case 0: il.Emit(OpCodes.Ldarg_1); break; case 1: il.Emit(OpCodes.Ldarg_2); break; case 2: il.Emit(OpCodes.Ldarg_3); break; default: il.Emit(OpCodes.Ldarg_S, x + 1); break; } if (xType.GetTypeInfo().IsValueType) { il.Emit(OpCodes.Box, xType); } il.Emit(OpCodes.Stelem_Ref); } } else { invoke = ImplementingType.GetMethod(operation.Name, operation.ParameterTypes); for (byte x = 0; x < operation.ParameterTypes.Length; x++) { switch (x) { case 0: il.Emit(OpCodes.Ldarg_1); break; case 1: il.Emit(OpCodes.Ldarg_2); break; case 2: il.Emit(OpCodes.Ldarg_3); break; default: il.Emit(OpCodes.Ldarg_S, x + 1); break; } } } il.Emit(OpCodes.Call, invoke); il.Emit(OpCodes.Ret); builder.DefineMethodOverride(mb, operation.MethodInfo); } } }