表达式:使用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 < ...
随机推荐
- Technology Trader
zoj2071:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2071 题意:题意一些零件,每一个零件会有一个花费,然后用这 ...
- 【POJ3208】 (DP)
Apocalypse Someday Description The number 666 is considered to be the occult “number of the beast” a ...
- crontab(linux下定时执行任务命令)
在linux在可以通过在脚本里(列如sh)写如日常需要进行的操作,然后通过crontab定时运行脚本. Linux下的任务调度分为两类,系统任务调度和用户任务调度. 系统任务调度:系统周期性所要执行的 ...
- maven错误解决:编码GBK的不可映射字符
直接将项目改为UTF-8编码,无效! 要通过修改pom.xml文件,告诉maven这个项目使用UTF-8来编译. 方案一: 在pom.xml的/project/build/plugins/下的编译插件 ...
- HDU-4272 LianLianKan
http://acm.hdu.edu.cn/showproblem.php?pid=4272 据说是状态压缩,+dfs什么什么的,可我这样也过了,什么算法都是浮云 ,暴力才是王道.我也归类为状态压缩, ...
- leetcode 最大矩形和
1.枚举法(超时) public class Solution { public int largestRectangleArea(int[] height) { int max=-1; for(in ...
- bzoj 2819 Nim(BIT,dfs序,LCA)
2819: Nim Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1596 Solved: 597[Submit][Status][Discuss] ...
- octopress 如何添加youku视频和本地视频(octopress how to add a youku video or a local video)
用octopress 官方的video tag 可以添加视频,但是由于国内经常使用的是youku,所以下面是如何添加youku视频到octopress的教程. 首先添加youku.rb文件到路径:oc ...
- [Java] Java IO 概况
Java IO 是 Java 的一套 API, 用于读入和写出数据(输入和输出).Java IO API 位于 java.io package.实际上 java.io package 没有解决所有的输 ...
- google API的.NET库
Goolge发布了一个新的google API .NET库,是一个Portable Class Library,所以无论是.NET,WinTRy,Windows Phone或者Silverlight都 ...