// 重写响应成员调用方法 public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) { // 获得真正的对象 DynamicType2 target = (DynamicType2)base.Value; Expression self = Expression.Convert(base.Expression, typeof(DynamicType2)); var restrictions = BindingRestrictions.GetInstanceRestriction(self, target); // 输出绑定方法名 Console.WriteLine(binder.Name + " 方法被调用了"); return(new DynamicMetaObject(self, restrictions)); }
internal Metadynamic(Expression expression, DynamicType2 value) : base(expression, BindingRestrictions.Empty, value) { }
static void Main(string[] args) { //详细了解 //http://blog.csdn.net/learning_hard/article/details/17456641 #region 引入动态类型 //在4.0为什么要引入动态类型 //我们都知道C#是静态类型语言,就算用了隐式类型var,也要必须初始化,让编译器确定其类型 //引入dynamic关键字来定义动态类型,编译器并不知道其类型,只有在程序运行时,才能被确定 string str = "20"; int x = 10; //x = str + x;//报错 x = int.Parse(str) + x; //要想编译成功就要转换 dynamic strtest = "20"; //x = strtest + x; //好处 //1、可以减少类型转换的使用 //2、调用Python等动态语言 // 引入动态类型之后 // 可以在C#语言中与动态语言进行交互 // 下面演示在C#中使用动态语言Python ScriptEngine engine = Python.CreateEngine(); Console.Write("调用Python语言的print函数输出: "); // 调用Python语言的print函数来输出 engine.Execute("print 'Hello world'"); #endregion #region 动态类型背后的故事 //这里不的不提DLR(Dynamic Language Runtime) //它的作用是什么,一句话:DLR就是帮助C#编译器来识别动态类型 //那DLR和CLR有什么关系呢,DLR是建立在CLR的基础之上的,DLR是动态语言和C#编译器用来动态执行代码的库,它不具有JIT和GC的功能 //DLR扮演了什么角色:DLR通过它的绑定器(binder)和调用点(callsite),元对象来把代码转换为表达式树, //*******************然后再把表达式树编译为IL代码,最后由CLR编译为机器可识别代码 #endregion #region 动态类型的约束 1234 //由于动态类型的不确定性让它不能做很多事 //1、不能调用扩展方法 var numbers = Enumerable.Range(10, 10); dynamic number = 4; //var error = numbers.Take(number); // 编译时错误 // 通过下面的方式来解决这个问题 // 1. 将动态类型转换为正确的类型 var right1 = numbers.Take((int)number); // 2. 用调用静态方法的方式来进行调用 var right2 = Enumerable.Take(numbers, number); //2、委托与动态类型不能做隐式转换 //dynamic lambdady = x => x + 1;//报错 //解决这个问题转换 dynamic lambdady = (Func <int, int>)(xx => xx + 1); //3、不能调用静态方法和构造函数 //dynamic testdy = new dynamic();报错 //4、类型声明和泛型类型参数(基类不能为dynamic类型、dynamic类型不能为类型参数的约束、不能作为所实现接口的一部分 ) #endregion #region 实现自己的动态行为(ExpandoObject、DynamicObject、IDynamicMetaObjectProvider) //ExpandoObject dynamic expando = new ExpandoObject(); expando.Name = "Roman"; expando.Addmethod = lambdady; Console.WriteLine("动态类型名称:{0}", expando.Name); Console.WriteLine("动态类型方法:{0}", expando.Addmethod); Console.WriteLine("调用动态类型方法:{0}", expando.Addmethod(5)); //DynamicObject重写 dynamic dynamicobj = new DynamicType(); dynamicobj.call = lambdady; dynamicobj.call(5); dynamicobj.Name = "Roman"; dynamicobj.Age = "24"; //实现IDynamicMetaObjectProvider接口 //由于Dynamic类型在运行时来动态创建对象的,所以对该类型的每个成员的访问都会调用GetMetaObject方法来获得动态对象, //然后通过这个动态对象来进行调用,所以实现IDynamicMetaObjectProvider接口,需要实现一个GetMetaObject方法来返回DynamicMetaObject对象 dynamic dynamicobj2 = new DynamicType2(); dynamicobj2.Call(); Console.Read(); #endregion Console.ReadKey(); }