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. Python connect zookeeper use the kazoo module

    doc:http://kazoo.readthedocs.org/en/latest/basic_usage.html eg: from kazoo.client import KazooClient ...

  2. MySQL协议简单分析

     tcpdump -i eth0 -s0  -l -w - port 3306|strings|grep -i -E 'select|update|insert|delete|set' 

  3. 【LA2796】Concert Hall Scheduling(最大费用最大流)

    Description You are appointed director of a famous concert hall, to save it from bankruptcy. The hal ...

  4. 项目经验谈---IM新消息界面刷新异常处理记录

    项目中使用到ContentObserver来观察Provider的变化,当对Uri做数据库操作时对应的Provider会发一条Notify消息调用UI上层的ContentChange方法,在这个Con ...

  5. 2.5.3 使用alertDialog创建自定义对话框

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout ...

  6. easy_install和pip区别

    easy_insall的作用和perl中的cpan, ruby中的gem类似,都提供了在线一键安装模块的傻瓜方便方式,而pip是easy_install的改进版, 提供更好的提示信息,删除packag ...

  7. 数据结构(分块):[HZOI 2015]easy seq

    [题目描述] 给定一个序列,下标从0开始,分别为a0,a1,a2...an−1,有m个询问,每次给出l和r,求满足ai=aj且l<=i<=j<=r时j−i的最大值 本题强制在线,l和 ...

  8. [Struts] Hello World Demo

    Struts 是一个基于 MVC 模式的框架.Struts 2 并不是 Struts 的下一个版本,几乎重写了 Struts.本文中提到的 Struts 均指 Struts 2. Model, 负责维 ...

  9. TOYS - POJ 2318(计算几何,叉积判断)

    题目大意:给你一个矩形的左上角和右下角的坐标,然后这个矩形有 N 个隔板分割成 N+1 个区域,下面有 M 组坐标,求出来每个区域包含的坐标数.   分析:做的第一道计算几何题目....使用叉积判断方 ...

  10. 敏捷开发松结对编程系列:L型代码结构案例StatusFiltersDropdownList(中)

    这是松结对编程的第22篇(专栏目录). 接前文 业务代码 比较长,基本上就是看被注释隔开的三大段,先显示状态群筛选链接,然后是单个状态筛选,然后是显示下拉框的当前选中项,最后显示下拉框. public ...