热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

具有参考变量的C#lambda委托调用方法

以下代码仅适用于没有引用参数的调用方法。publicdelegatevoidtestD2(paramsobject[]args)

以下代码仅适用于没有引用参数的调用方法。

public delegate void testD2(params object[] args);
public static testD2 SetTestD2(MethodInfo method)
{
ParameterExpression param = Expression.Parameter(typeof(object[]),"args");
ParameterInfo[] paramsInfo = method.GetParameters();
Expression[] argsExp = new Expression[paramsInfo.Length];
for (int i = 0; i {
Expression index = Expression.Constant(i);
Type paramType = paramsInfo[i].ParameterType;
//??? ByRef removed from type,becuse Expression.Call with ByRef parametrs lead to compile error
if (paramType.IsByRef == true)
paramType = paramType.GetElementType();
//??? and for this reason is not change of parameters permanent
Expression paramaccessorExp = Expression.ArrayIndex(param,index);
Expression paramCastExp = Expression.Convert(paramaccessorExp,paramType);
argsExp[i] = paramCastExp;
}
var blockExp = Expression.Call(method,argsExp);
LambdaExpression result = Expression.Lambda(typeof(testD2),blockExp,param); //change in param?
return (testD2)result.Compile();
}

我正在考虑更改通过params关键字传递的输入参数,或者为lambda创建新的参数,但是我不知道如何。

public class testCls
{
public void Test()
{
MethodInfo mi = typeof(XXX).GetMethod("TestMethod");
var compiledObject2 = XXX.SetTestD2(mi);
int k = 5;
compiledObject2(k); //k is not passed as ByRef
}
}
public static void TestMethod(ref int a)
{
a = a * a;
}


refout参数与params不兼容,我认为这是基本语言或运行时限制。

要执行所需的操作,可以将其编译为正确类型的强类型委托。 Expression.GetDelegateType呼叫可以为您创建正确的类型;与params object[]不同,可以有输出和参考参数。

,

强类型委托是一种方法,但是对于各种方法需要额外的代码。这就是为什么我尝试使用通用函数来创建通用委托的原因。
对于关键字params,我认为如果该函数被经典地调用DelegateSomeFunc(a,b,c,),则不会通过引用传递任何内容。但是,如果该函数由数组调用,则参数将通过引用传递。

int k = 5;
string b = "aa";
object[] objArr = { k,b };
compiledObject2(k,b); //parameters passed by value
compiledObject2(objArr); //array passed by reference (params don't need create new array?)

代表调用此功能

public static void TestMethod(ref int a,string text)
{
a = a * a;
}

理论上可以用函数创建委托,但是还有另一个问题-用表达式参数数组而不是表达式数组调用函数。
原始帖子中的上面的代码排了一行

var blockExp = Expression.Call(method,argsExp);

但是argsExp可能无法返回函数更改的参数。因此,我将输入参数写在局部表达式变量中,称为函数的函数可以更改,最后将更改后的值放在输入参数数组中。

public static Class1.testD2 SetTestD2(System.Reflection.MethodInfo method)
{
ParameterExpression param = Expression.Parameter(typeof(object[]),"args"); // Expression.Parameter(typeof(object[]),"args");
BinaryExpression[] byExp=null;
Expression[] argsExp = GetArgExp(method.GetParameters(),param,ref byExp);
ParameterExpression xxx = Expression.Variable(typeof(int));
ParameterExpression yyy = Expression.Variable(typeof(string));
var blockExp =
Expression.Block( new[] { xxx,yyy } //variables,Expression.Assign(xxx,argsExp[0]),Expression.Assign(yyy,argsExp[1]),Expression.Call(method,xxx,yyy),Expression.Assign(Expression.ArrayAccess(param,Expression.Constant(0)),Expression.Convert(xxx,typeof(object))) //change input param array
) ;
LambdaExpression result = Expression.Lambda(typeof(testD2),blockExp,param);
return (testD2)result.Compile();
}

该功能只是更改输入参数的示例。现在可以返回更改的参数。

MethodInfo mi = typeof(Class1).GetMethod("TestMethod");
var compiledObject2 = Class1.SetTestD2(mi);
int k = 5;
string b = "aa";
object[] objArr = { k,b); //no changes
compiledObject2(objArr); //objArr[0] changed

但是我不知道函数是否可以修改创建委托的通用委托。


推荐阅读
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文介绍了解决java开源项目apache commons email简单使用报错的方法,包括使用正确的JAR包和正确的代码配置,以及相关参数的设置。详细介绍了如何使用apache commons email发送邮件。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
author-avatar
martinsleibert_471
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有