I am trying to implement interface for dynamic generated class/method. The implementation is okay for method with one args(commented in code). But when method has two or more params it is throwing "Exception has been thrown by the target of an invocation". Unable to figureout what is wrong with two args? Any help would be appreciated. Below is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Net.Http;
using System.Reflection;
using System.Reflection.Emit;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Controllers;
namespace ConsoleApplication7
{
public class Foo
{
public string Bar(string m)
{
return m;
}
}
public interface IFoo
{
string Barz(int i, int s);
//string Barz(int i);// works good
}
public class Program
{
public string my(int w, int s)
{
return (s + w).ToString();
}
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public void TestMethod()
{
var ab = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("TestAssembly"), AssemblyBuilderAccess.RunAndSave);
var mb = ab.DefineDynamicModule("Test");
var tb = mb.DefineType("Foo", typeof(Foo).Attributes, typeof(Foo));
tb.AddInterfaceImplementation(typeof(IFoo));
foreach (var imethod in typeof(IFoo).GetMethods())
{
var method =
tb.DefineMethod
(
"@@" + imethod.Name,
MethodAttributes.Private | MethodAttributes.Static,
CallingConventions.Standard,
imethod.ReturnType,
imethod.GetParameters().Select(n => n.ParameterType).ToArray()
);
var thisParameter = Expression.Parameter(typeof(IFoo), "this");
var param = new ParameterExpression[] { Expression.Parameter(typeof(int)), Expression.Parameter(typeof(int)) };
var bodyExpression =
Expression.Lambda<Func<int,int, string>>(
Expression.Call(
Expression.New(typeof(Program)),
typeof(Program).GetMethod("my", new Type[] { typeof(int), typeof(int) }), param
), param);
//var y = bodyExpression.Compile();//compiles good
// var p = y.Invoke(200, "");//invocation is ok
bodyExpression.CompileToMethod(method);
var mp = imethod.GetParameters().Select(r => r.ParameterType).ToArray();
var stub =
tb.DefineMethod(imethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, CallingConventions.Standard,
imethod.ReturnType, mp);
var il = stub.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Call, method, null);
il.Emit(OpCodes.Ret);
tb.DefineMethodOverride(stub, imethod);
}
var type = tb.CreateType();
ab.Save("test.dll");
var obj = CreateAndInvoke(type, null, "Barz", null);
Console.ReadLine();
}
public static object CreateAndInvoke(Type typeName, object[] constructorArgs, string methodName, object[] methodArgs)
{
Type type = typeName;
object instance = Activator.CreateInstance(type);
object[] a = new object[] { 900 ,0};
MethodInfo method = type.GetMethod(methodName);
return method.Invoke(instance, a);//issue over here
}
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public static void Main(string[] args)
{
new Program().TestMethod();
}
}
}