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的更多相关文章

  1. 表达式:使用API创建表达式树(3)

    一.DebugInfoExpression:发出或清除调试信息的序列点. 这允许调试器在调试时突出显示正确的源代码. static void Main(string[] args) { var asm ...

  2. 表达式:使用API创建表达式树(2)

    一.BlockExpression类:表式一个包含可在其中定义变量的表达式序列的块.是一组表达式,类似于多个委托的 += 后的效果,其返回表达式是最后一个表达式决定.以下是BlockExpressio ...

  3. 表达式:使用API创建表达式树(1)

    表达式树可使用Expressions类的静态工厂方法来创建.这种用API的方式创建给予我们在编程极大的灵活性,MSDN上关于表达式的例子也不少,但在使用过程中还是会遇到许多麻烦,对有的表达式类,介绍得 ...

  4. 表达式:使用API创建表达式树(6)

    一.ConstantExpression:表示具有常量值的表达式.因为表达式应用过程中,参数据多是 Expressions 类型,算是对常量值的一种包装吧. ConstantExpression使用比 ...

  5. 表达式:使用API创建表达式树(5)

    一.ConditionalExpression:表达式 生成如 IIF((a == b), "a和b相等", "a与b不相等") 式子. 使用: Paramet ...

  6. EF4.0、4.3创建表达式树状动态查询总结

    ---------------------------------------------快速适用 效果: where name like '%王%' and Age>=35 or Age< ...

  7. 【C#表达式树 五】工厂模式创建表达式树节点

    常量 1.值常量  (p)=>100+88+p ParameterExpression par = Expression.Parameter(typeof(int), "p" ...

  8. [C# Expression] 之动态创建表达式

    上一篇中说到了 Expression 的一些概念性东西,其实也是为了这一篇做知识准备.为了实现 EFCore 的多条件.连表查询,简化查询代码编写,也就有了这篇文章.   在一些管理后台中,对数据进行 ...

  9. NX二次开发-NX11创建表达式组NXOpen::ExpressionGroup

    NX11+VS2013 #include <uf.h> #include <uf_modl.h> #include <uf_part.h> #include < ...

随机推荐

  1. NWERC 2012 Problem E Edge Case

    比赛的时候刷了一点小聪明,发现这个数列是卢卡斯数,一个递推关系像斐波拉契数列的数列: 我不知道怎么证明,如果哪天无意中会证了再加上: 这题唯一的难点就是大数运算: 直接用JAVA 代码: import ...

  2. Technology Trader

    zoj2071:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2071 题意:题意一些零件,每一个零件会有一个花费,然后用这 ...

  3. WPF 界面布局DockPanel stackPanel WrapPanel 元素内容以及位置控制

    1 DockPanel 1) 默认充满整个窗口. 2) 最后一个出现的部分,默认充满剩余空间. 3) 非最后一个出现的部分,根据其中内容,进行分配空间s 2 StackPanel 实现居左,居右,居中 ...

  4. 【HDOJ】2988 Dark roads

    最小生成树. /* */ #include <iostream> #include <string> #include <map> #include <que ...

  5. Robotium跨应用处理方法

    相信用过一段时间Robotium的同学一般都遇到过如下情况:界面跳转到被测程序外以后,Robotium就毫无对策了,这也是Instrumentation框架最致命的一个缺点;然而领导是不会管你这些很“ ...

  6. WordPress Ultimate Auction插件跨站请求伪造漏洞

    漏洞名称: WordPress Ultimate Auction插件跨站请求伪造漏洞 CNNVD编号: CNNVD-201306-396 发布时间: 2013-09-11 更新时间: 2013-09- ...

  7. 未能导入activex控件,请确保它正确注册"的完美解决方案

    这个错误“未能导入activex控件,请确保它正确注册”昨天下午让我和我同事花费了3个小时来调试这个错误,在使用VS2010的winfrom编程时加入com组件的时候,报这个错误(以一个客户的机器上) ...

  8. unity3d shader之实时室外光线散射(大气散射)渲染

    散射需要:吸收,内散射,外散射分为瑞利散射Rayleigh Scattering和米氏散射 Mie Scattering  后面会详细讲解 大气中散射由多种原因产生,微粒,尘埃,水蒸气等等 阳光由于散 ...

  9. (转载)ubuntu安装pyton-pip问题解决

    一.问题描述 root@ubuntu:/home/chao# apt-get install python-pip 正在读取软件包列表... 完成 正在分析软件包的依赖关系树 正在读取状态信息... ...

  10. Java---基于TCP协议的相互即时通讯小程序

    这是几年前,新浪的一个面试题~要求是3天之内实现~ 通过TCP 协议,建立一个服务器端. 通过配置服务器端的IP和端口: 客户端之间就可以相互通讯~ 上线了全部在线用户会收到你上线的通知. 下线了全部 ...