表达式:使用API创建表达式树(4)DynamicExpression
DynamicExpression:表示动态操作。这个网上可见的资料少得可怜,但想到MVC和第三方的动态语言能在NET运行。好奇的倒腾了下
先声明两个类(有相同的方法和字段,但不是继承于同一接口的类),设想是动态调用它们的方法和字段。
class AiTestD
{
public string Name = "你好!这是 AiTestD";
public int Id = ;
public static string AiTest(string ai1, string ai2)
{
return ai1 + ai2;
} public static int add(int a, int b)
{ return a + b;
} public int add2(int a, int b)
{ return -(a + b);
}
} class AiTestD2
{
public string Name = "你好!这是 AiTestD2";
public int Id = ;
public static string AiTest(string ai1, string ai2)
{
return "**" + ai1 + ai2;
}
public static int add(int a, int b)
{
return (a + b) * ;
}
public int add2(int a, int b)
{
return -(a + b) * ;
}
}
第一个方法 AiDynamicDo,要实现的是获取两个类的Id属性质(这里是值类型操作,刚开始时,定义的是typeof(Func<CallSite, object, int>,总是编译不过,发现在 Expression.MakeDynamic 中的参数,只要是值类型都是通不过的,只有通过Expression.Convert转换成 typeof(object),才可以,但引用类型是不用转换的)
/// <summary>
/// 获取字段
/// </summary>
/// <param name="aiD"></param>
static void AiDynamicDo(dynamic aiD)
{
//声明参数
ParameterExpression paramExpr = Expression.Parameter(typeof(object), "o");
//获取 CallSite 以支持调用时的运行时。
//CallSiteBinder 是必需的
//注意这里用的是 Binder.GetMember
CallSiteBinder aiBinder = Binder.GetMember(CSharpBinderFlags.None, "Id", typeof(Program),
new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) });
//定义一个动态表达式
//Func<CallSite, object, object>声明方式中 CallSite 是动态调用站点的基类。 此类型用作动态站点目标的参数类型。
//就是上面的 aiBinder,第二个参数是要传入的动态类型 用dynamic关键字也是可以的,
//后面的参数是实际调用和返回的参数
//不过操作中发现在返回值一定要用 object 不然会编译不过
//当然也可用Action<CallSite, object,...>,除了没返回值,参数要求和用Func<CallSite, object, object>是一样的。 DynamicExpression Dynamic2 =
Expression.MakeDynamic(typeof(Func<CallSite, object, object>),
aiBinder, paramExpr
);
//编译
LambdaExpression laExp = Expression.Lambda(
Expression.Block(
new ParameterExpression[] { paramExpr },
Expression.Assign(paramExpr, Expression.Constant(aiD))
, Dynamic2));
//执行
Console.WriteLine("AiDynamicDo:" + laExp.ToString());
Console.WriteLine("结果:" + laExp.Compile().DynamicInvoke());
Console.WriteLine(); }
调用:
AiDynamicDo(new AiTestD());
AiDynamicDo(new AiTestD2());
输出为:
AiDynamicDo:() => {var o; ... }
结果:123
AiDynamicDo:() => {var o; ... }
结果:789
/// <summary>
/// 字段2
/// </summary>
/// <param name="aiD"></param>
static void AiDynamicDo2(dynamic aiD)
{
//Binder.Convert
CallSiteBinder aiBinder = Binder.Convert(CSharpBinderFlags.None, typeof(object), typeof(Program));
ParameterExpression paramExpr = Expression.Parameter(aiD.GetType(), "o");
MemberExpression namePropExpr = Expression.Field(paramExpr, "Name");
var Dynamic2 = Expression.MakeDynamic(typeof(Func<CallSite, object, object>)
, aiBinder
, namePropExpr
);
LambdaExpression laExp = Expression.Lambda(
Expression.Block(
new ParameterExpression[] { paramExpr },
Expression.Block(Expression.Assign(paramExpr, Expression.Constant(aiD))
)
, Dynamic2));
Console.WriteLine("AiDynamicDo2:" + laExp.ToString());
Console.WriteLine("结果:" + laExp.Compile().DynamicInvoke());
Console.WriteLine();
} /// <summary>
/// 引用类型方法调用测试 Binder.Convert
/// </summary>
/// <param name="aiD"></param>
static void AiDynamicDo3(dynamic aiD)
{
//Binder.Convert
CallSiteBinder aiBinder = Binder.Convert(CSharpBinderFlags.None, typeof(object), typeof(Program));
ParameterExpression aiParamExpr = Expression.Parameter(aiD.GetType(), "o");
ParameterExpression aiParamExpr1 = Expression.Parameter(typeof(string), "a");
ParameterExpression aiParamExpr2 = Expression.Parameter(typeof(string), "b");
MethodCallExpression aiMth = Expression.Call(
null, aiD.GetType().GetMethod("AiTest", new Type[] { typeof(string), typeof(string) }), aiParamExpr1, aiParamExpr2);
var Dynamic2 =
Expression.MakeDynamic(
typeof(Func<CallSite, dynamic, object>),
aiBinder, aiMth );
LambdaExpression laExp = Expression.Lambda(Dynamic2, aiParamExpr1, aiParamExpr2);
Console.WriteLine("AiDynamicDo3:" + laExp.ToString());
Console.WriteLine("结果:" + laExp.Compile().DynamicInvoke("AiTest-", "动态调用"));
Console.WriteLine();
} /// <summary>
/// 值类型方法调用测试 Binder.Convert
/// </summary>
/// <param name="aiD"></param>
static void AiDynamicDo4(dynamic aiD)
{
CallSiteBinder aiBinder = Binder.Convert(CSharpBinderFlags.None, typeof(object), typeof(Program));
ParameterExpression aiParamExpr = Expression.Parameter(aiD.GetType(), "o");
ParameterExpression aiParamExpr1 = Expression.Parameter(typeof(int), "a");
ParameterExpression aiParamExpr2 = Expression.Parameter(typeof(int), "b"); MethodCallExpression aiMth = Expression.Call(
null, aiD.GetType().GetMethod("add", new Type[] { typeof(int), typeof(int) }), aiParamExpr1, aiParamExpr2);
var Dynamic2 =
Expression.MakeDynamic(
typeof(Func<CallSite, dynamic, object>),
aiBinder,
Expression.Convert(aiMth, typeof(object)) //!!这里要转换,否刚不能通过 );
//LambdaExpression laExp = Expression.Lambda(Dynamic2, paramExpr1, paramExpr2);
LambdaExpression laExp = Expression.Lambda(
Expression.Block(
new ParameterExpression[] { aiParamExpr1, aiParamExpr2 },
Expression.Block(Expression.Assign(aiParamExpr1, Expression.Constant()),
Expression.Assign(aiParamExpr2, Expression.Constant())
),
Dynamic2
)
);
Console.WriteLine("AiDynamicDo4:" + laExp.ToString());
Console.WriteLine("结果:" + laExp.Compile().DynamicInvoke());
Console.WriteLine();
} //与上例不同的是,本过程不是调用的反射方法
static void AiDynamicDo5(dynamic aiD)
{
//当调用方法是void类型时 应该用 CSharpBinderFlags.ResultDiscarded
//第二个参数是方法名
//第三个参数要泛型时才结出
//第五个参数要与表达示参数据相同
var aiBinder = Binder.InvokeMember(CSharpBinderFlags.None, "add2", null, typeof(Program),
new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }); ParameterExpression aiParamExpr = Expression.Parameter(typeof(object), "o");
ParameterExpression aiParamExpr1 = Expression.Parameter(typeof(int), "a");
ParameterExpression aiParamExpr2 = Expression.Parameter(typeof(int), "b");
//与上例中不同的地方
DynamicExpression aiDynamic = Expression.MakeDynamic(typeof(Func<CallSite, object, int, int, object>)
, aiBinder
, aiParamExpr
, aiParamExpr1
, aiParamExpr2 );
//下面这种使用方式,在调用时DynamicInvoke(aiD,30,40)
//LambdaExpression laExp = Expression.Lambda(Dynamic2, paramExpr, paramExpr1, paramExpr2);
LambdaExpression aiLabExp = Expression.Lambda(
Expression.Block(
new ParameterExpression[] { aiParamExpr, aiParamExpr1, aiParamExpr2 }
, Expression.Assign(aiParamExpr, Expression.Constant(aiD))
, Expression.Assign(aiParamExpr1, Expression.Constant())
, Expression.Assign(aiParamExpr2, Expression.Constant())
, aiDynamic)); Console.WriteLine("AiDynamicDo5:" + aiLabExp.ToString());
Console.WriteLine("结果:" + aiLabExp.Compile().DynamicInvoke());
Console.WriteLine();
}
调用:
AiDynamicDo2(new AiTestD());
AiDynamicDo2(new AiTestD2());
AiDynamicDo3(new AiTestD());
AiDynamicDo3(new AiTestD2());
AiDynamicDo4(new AiTestD());
AiDynamicDo4(new AiTestD2());
AiDynamicDo5(new AiTestD());
AiDynamicDo5(new AiTestD2());
输出:
AiDynamicDo2:() => {var o; ... }
结果:你好!这是 AiTestD
AiDynamicDo2:() => {var o; ... }
结果:你好!这是 AiTestD2
AiDynamicDo3:(a, b) => Convert System.Object(AiTest(a, b))
结果:AiTest-动态调用
AiDynamicDo3:(a, b) => Convert System.Object(AiTest(a, b))
结果:**AiTest-动态调用
AiDynamicDo4:() => {var a;var b; ... }
结果:70
AiDynamicDo4:() => {var a;var b; ... }
结果:70000
AiDynamicDo5:() => {var o;var a;var b; ... }
结果:-70
AiDynamicDo5:() => {var o;var a;var b; ... }
结果:-70000
表达式:使用API创建表达式树(4)DynamicExpression的更多相关文章
- 表达式:使用API创建表达式树(3)
一.DebugInfoExpression:发出或清除调试信息的序列点. 这允许调试器在调试时突出显示正确的源代码. static void Main(string[] args) { var asm ...
- 表达式:使用API创建表达式树(2)
一.BlockExpression类:表式一个包含可在其中定义变量的表达式序列的块.是一组表达式,类似于多个委托的 += 后的效果,其返回表达式是最后一个表达式决定.以下是BlockExpressio ...
- 表达式:使用API创建表达式树(1)
表达式树可使用Expressions类的静态工厂方法来创建.这种用API的方式创建给予我们在编程极大的灵活性,MSDN上关于表达式的例子也不少,但在使用过程中还是会遇到许多麻烦,对有的表达式类,介绍得 ...
- 表达式:使用API创建表达式树(6)
一.ConstantExpression:表示具有常量值的表达式.因为表达式应用过程中,参数据多是 Expressions 类型,算是对常量值的一种包装吧. ConstantExpression使用比 ...
- 表达式:使用API创建表达式树(5)
一.ConditionalExpression:表达式 生成如 IIF((a == b), "a和b相等", "a与b不相等") 式子. 使用: Paramet ...
- EF4.0、4.3创建表达式树状动态查询总结
---------------------------------------------快速适用 效果: where name like '%王%' and Age>=35 or Age< ...
- 【C#表达式树 五】工厂模式创建表达式树节点
常量 1.值常量 (p)=>100+88+p ParameterExpression par = Expression.Parameter(typeof(int), "p" ...
- [C# Expression] 之动态创建表达式
上一篇中说到了 Expression 的一些概念性东西,其实也是为了这一篇做知识准备.为了实现 EFCore 的多条件.连表查询,简化查询代码编写,也就有了这篇文章. 在一些管理后台中,对数据进行 ...
- NX二次开发-NX11创建表达式组NXOpen::ExpressionGroup
NX11+VS2013 #include <uf.h> #include <uf_modl.h> #include <uf_part.h> #include < ...
随机推荐
- mac下设置命令别名
项目使用了gerrit,每次push代码都需要执行 git push origin HEAD:refs/for/master 为了简便,使用了alias命令来控制台下使用下面的命令简化了提交. ali ...
- 用SharedPreferences保存List(Map(String, String))数据
原因: SharedPreferences没有保存数组的方法,但是有时候为了保存一个数组而进行序列化,或者动用sqlite都是有点杀猪焉用牛刀的感觉,所以就自己动手改进一下吧. 解决方案: 采用的方式 ...
- 10.在Global全局文件中的Application_BeginRequest示例
只要有人访问本网站,都要执行全局文件的Application_BeginRequest事件.因此我们可以防盗链. 示例要求:凡不是网站本机登录的都给客户端提示,用图片显示. 分析:由于网页在加载时不是 ...
- Java 比较两个字符串的大小
比较两个字符串的大小 static int compareTo(String s1, String s2) { int len1 = s1.length(); int len2 = s2.length ...
- Java-Iterator的用法
迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭代器通常被称为“轻量级”对象,因为创建它的代价小. Java中的I ...
- 【转】使用unity3d需要注意到细节
原 文:http://cache.baiducontent.com /c?m=9d78d513d9841df41ea6837e7c01a6660e20f6743da7c76508c3e34f84152 ...
- HDOJ/HDU 2566 统计硬币(公式~遍历~)
Problem Description 假设一堆由1分.2分.5分组成的n个硬币总面值为m分,求一共有多少种可能的组合方式(某种面值的硬币可以数量可以为0). Input 输入数据第一行有一个正整数T ...
- Java程序员必知的8大排序算法
8种排序之间的关系 直接插入排序 (1)基本思想:在要排序的一组数中,假设前面(n-1)[n>=2] 个数已经是排 好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数 也是排好顺序的.如 ...
- Java GC 专家系列5:Java应用性能优化的原则
本文是GC专家系列中的第五篇.在第一篇理解Java垃圾回收中我们学习了几种不同的GC算法的处理过程,GC的工作方式,新生代与老年代的区别.所以,你应该已经了解了JDK 7中的5种GC类型,以及每种GC ...
- Working XML: Processing instructions and parameters
Adding support for multiple style sheets This month our hardworking columnist(专栏作家) adds support for ...