表达式:使用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 < ...
随机推荐
- BZOJ 1001 狼捉兔子
Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个 ...
- 自定义元素–为你的HTML代码定义新元素
注意:这篇文章介绍的 API 尚未完全标准化,并且仍在变动中,在项目中使用这些实验性 API 时请务必谨慎. 引言 现在的 web 严重缺乏表达能力.你只要瞧一眼“现代”的 web 应用,比如 GMa ...
- Git如何Check Out出指定文件或者文件夹
原文 http://www.handaoliang.com/a/20140506/195406.html 在进行项目开发的时候,有时候会有这样的需求那就是:我们只希望从Git仓库里取指定的文件或者文 ...
- 【UVA10829】 L-Gap Substrings (后缀数组)
Description If a string is in the form UVU, where U is not empty, and V has exactly L characters, we ...
- struts2表单验证
1:采用手工编写代码实现. 通过继承ActionSupport类,然后重写vlidate方法,validate方法会校验跟execute同样签名的方法,当某个数据校验失败时,我们应该调用addFiel ...
- 《深度探索c++对象模型》chapter2 构造函数语义学
关于c++,最常听到的一个抱怨是,编译器背着程序员做了太多事情,conversion运算符是最常被引用的一个例子:jerry schwarz,iostream函数库的建筑师,就曾经说过一个故事,他说他 ...
- gitweb安装
gitweb安装: 1. 简介 Gitweb提供了git版本库的图形化web浏览功能.可以到网站http://git.kernel.org/体验下效果,如下图所示. Gitweb界面 它既可以通过配置 ...
- -_-#【Markdown】
nswbmw / N-blog 第2章 使用 Markdown Markdown 语法说明 (简体中文版)Markdown: Basics (快速入门) 这里示范了一些 Markdown 的语法, 请 ...
- IIS7 上传 下载文件大小限制的设置
IIS7 上传 下载文件大小限制的设置 本文来自IISBOY网 一.找到修改大小的配置文件和配置节点 本文来自IISBOY网 打开你系统盘(我是C盘),找到 C:\Windows\System32\i ...
- JavaScript XML 兼容处理,序列化和反序列化以及回调事件
浏览器中XML DOM的支持 IE中通过ActiveXObject实现了XML的支持,存在一下几个版本:Microsoft.XmlDom,MSXML2.DOMDocument,MSXML2.DOMDo ...