Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# IL生成用户定义函数的代理(<;TInput、TReturn>;_C#_Reflection_.net Core_Code Generation - Fatal编程技术网

C# IL生成用户定义函数的代理(<;TInput、TReturn>;

C# IL生成用户定义函数的代理(<;TInput、TReturn>;,c#,reflection,.net-core,code-generation,C#,Reflection,.net Core,Code Generation,我试图动态生成一个程序集来调用用户创建的func private MethodBuilder DefineGetMethod<TInput, TReturn>( TypeBuilder tb, MethodDescriptor methodInfo, Func<TInput, TReturn> dynamicMethod) { //Define the function var dynamicMethodBuilder = tb.DefineMe

我试图动态生成一个程序集来调用用户创建的func

private MethodBuilder DefineGetMethod<TInput, TReturn>(
     TypeBuilder tb, MethodDescriptor methodInfo, Func<TInput, TReturn> dynamicMethod)
{
    //Define the function
    var dynamicMethodBuilder = tb.DefineMethod(methodInfo.MethodName,
              MethodAttributes.Public,
              methodInfo.ReturnType, methodInfo.InputParameters.Select(x => x.Type).ToArray());

    //Define the labels for the method inputs
    for(var i = 0; i < methodInfo.InputParameters.Length; i++ )
    {
        // Position 0 is the return value, 1 is the 1st param, 2 is 2nd, etc.
        var position = 1 + i;
        var inputParam = methodInfo.InputParameters[i];
        dynamicMethodBuilder.DefineParameter(position, ParameterAttributes.None, inputParam.Name);
    }

    var ilGenerator = dynamicMethodBuilder.GetILGenerator();

    //Loads arg1
    ilGenerator.Emit(OpCodes.Ldarg_1);

    //Not sure how to pass the arg1 to the method body to return
    var ilMethodBody = dynamicMethod.Method.GetMethodBody().GetILAsByteArray();

    //Generates return
    ilGenerator.Emit(OpCodes.Ret);

}

如何将加载的参数传递给
ilMethodBody
并返回?

EDIT-Johnny 5

事实证明,您可以对现有的方法信息执行一个跳转语句:

myMethodIL.Emit(OpCodes.Jmp, method.Method);
myMethodIL.Emit(OpCodes.Ret);
首先,您必须确保
TReturn
等于
methodInfo.ReturnType
TInput
等于
methodInfo.InputParameters
中的第一个

如果
dynamicMethod
是一个静态方法委托,那么它将很简单,如:

私有MethodBuilder定义方法(TypeBuilder tb、MethodDescriptor methodInfo、Func dynamicMethod)
{
var dynamicMethodBuilder=tb.DefineMethod(methodInfo.MethodName,
MethodAttributes.Public | MethodAttributes.hidebysing,
methodInfo.ReturnType、methodInfo.InputParameters.Select(x=>x.Type.ToArray());
var ilGenerator=dynamicMethodBuilder.GetILGenerator();
ilGenerator.Emit(操作码.Ldarg_1);
Emit(操作码.Call,dynamicMethod.Method);
ilGenerator.Emit(操作码.Ret);
返回dynamicMethodBuilder;
}
但是如果
dynamicMethod
可能是一个实例方法(lambda with be a instance method),那么它将很难实现。调用实例方法需要首先将实例推送到堆栈上,但是
Emit
只允许推常量值,如int、string

我只能想到一种方法,声明一个字段来存储
dynamicMethod
,通过反射在构建类型之后设置字段值:

私有类型定义方法(TypeBuilder tb、MethodDescriptor methodInfo、Func dynamicMethod)
{
var fieldBuilder=tb.DefineField(“_func”,dynamicMethod.GetType(),FieldAttributes.Private | FieldAttributes.Static);
var dynamicMethodBuilder=tb.DefineMethod(methodInfo.MethodName,
MethodAttributes.Public | MethodAttributes.hidebysing,
methodInfo.ReturnType、methodInfo.InputParameters.Select(x=>x.Type.ToArray());
var ilGenerator=dynamicMethodBuilder.GetILGenerator();
//将静态字段_func加载到堆栈上
ilGenerator.Emit(操作码.Ldsfld,fieldBuilder);
//将arg1加载到堆栈上
ilGenerator.Emit(操作码.Ldarg_1);
//调用函数调用(..)
Emit(opcode.Callvirt,dynamicMethod.GetType().GetMethod(“调用”));
ilGenerator.Emit(操作码.Ret);
var type=tb.CreateType();
var field=type.GetField(“_func”,BindingFlags.NonPublic | BindingFlags.Static);
//将dynamicMethod存储到静态字段_func
field.SetValue(null,dynamicMethod);
返回类型;
}
编辑

测试代码:

类程序
{
静态void Main(字符串[]参数)
{
onystaticfunc();
StaticField();
}
静态void onystaticfunc()
{
Func Func=int.Parse;
var assemblyName=新的assemblyName(“StaticFuncTest”);
var assemblyBuilder=assemblyBuilder.definedDynamicAssembly(assemblyName,AssemblyBuilderAccess.Run);
var moduleBuilder=assemblyBuilder.DefinedDynamicModule(assemblyName.Name);
var typeBuilder=moduleBuilder.DefineType(“Abc”,TypeAttributes.Public);
var methodBuilder=typeBuilder.DefineMethod(“Execute”,MethodAttributes.Public | MethodAttributes.HideBySig,typeof(int),new[]{typeof(string)});
var il=methodBuilder.GetILGenerator();
il.Emit(操作码Ldarg_1);
发射(操作码调用,函数方法);
发射(操作码Ret);
var type=typeBuilder.CreateType();
var abc=Activator.CreateInstance(类型);
var值=((动态)abc).Execute(“123”);
WriteLine($“仅静态函数:{value}”);
}
静态void StaticField()
{
Func Func=s=>int.Parse(s);
var assemblyName=新的assemblyName(“StaticFieldTest”);
var assemblyBuilder=assemblyBuilder.definedDynamicAssembly(assemblyName,AssemblyBuilderAccess.Run);
var moduleBuilder=assemblyBuilder.DefinedDynamicModule(assemblyName.Name);
var typeBuilder=moduleBuilder.DefineType(“Abc”,TypeAttributes.Public);
var fieldBuilder=typeBuilder.DefineField(“_func”,func.GetType(),FieldAttributes.Private | FieldAttributes.Static”);
var methodBuilder=typeBuilder.DefineMethod(“Execute”,MethodAttributes.Public | MethodAttributes.HideBySig,typeof(int),new[]{typeof(string)});
var il=methodBuilder.GetILGenerator();
il.Emit(操作码.Ldsfld,fieldBuilder);
il.Emit(操作码Ldarg_1);
Emit(OpCodes.Callvirt,func.GetType().GetMethod(“Invoke”));
发射(操作码Ret);
var type=typeBuilder.CreateType();
var field=type.GetField(“_func”,BindingFlags.NonPublic | BindingFlags.Static);
field.SetValue(null,func);
var abc=Activator.CreateInstance(类型);
var值=((动态)abc)。执行(“456”);
WriteLine($“静态字段:{value}”);
}
}

ilGenerator.Emit(OpCodes.Callvirt,dynamicMethod.Method)怎么样。这看起来很有希望,能通过参数吗?今晚晚些时候我会测试谢谢,今晚有机会测试后我会把这个标记完整。这不完全是我想要的,但它可以工作,所以我不能抱怨:)我找到了方法,我编辑了你的答案,所以现在你有三种不同的方法来完成它:D新知识,明白了吗
myMethodIL.Emit(OpCodes.Jmp, method.Method);
myMethodIL.Emit(OpCodes.Ret);