C#学习笔记(十一):动态类型
2015-07-13 19:26
477 查看
C#是一门静态类型的语言,但是在C#4.0时微软引入了动态类型的概念。
我们的两个类没有继承也没有应用相同的接口,但是可以调用到相同的方法,使用GetObject(1)可以得到想要的结果。
这就是动态类型,在编译时不会对方法等进行判断,而是在运行时才进行处理,如果调用到不存在的方法才会报错。
C#编译器允许你通过dynamic对象调用任何方法,即使这个方法根本不存在,编译器也不会在编译的时候报编译错误。只有在运行的时候,它才会检查这个对象的实际类型,并检查在它上面Talk()是什么意思。动态类型将使得C#可以以更加统一而便利的形式表示下列对象:
来自动态编程语言——如Python或Ruby——的对象;
通过IDispatch访问的COM对象;
通过反射访问的一般.NET类型;
结构发生过变化的对象——如HTML DOM对象;
当我们得到一个动态类型的对象时,不管它是来自COM还是IronPython、HTML DOM还是反射,只需要对其进行操作即可,动态语言运行时(DLR)会帮我们指出针对特定的对象以及这些操作的具体意义。这将给我们的开发带来极大的灵活性,并且能够极大程度上地精简我们的代码。
委托与动态类型不能进行隐式转换;
不能调用构造函数和静态方法;
类不能继承dynamic、泛型参数不能使用dynamic和接口实现也不能使用dynamic;
输出如下:
输出如下:
输出如下:
dynamic
关键字dynamic用来定义动态对象,我们来看一下动态类型的一些特性。调用不同类的相同方法
我们有两个或多个不相关的类,然后运行时需要可以调用到相同名称的方法,如下:using System; namespace Study { class Program { static void Main(string[] args) { dynamic obj = GetObject(0); Console.WriteLine(obj.Talk()); Console.Read(); } private static Object GetObject(int type) { switch (type) { case 1: return new Dog(); } return new Robot(); } } public class Dog { public string Talk() { return "Wang Wang!"; } } public class Robot { public string Talk() { return "I`m a Robot!"; } } }
我们的两个类没有继承也没有应用相同的接口,但是可以调用到相同的方法,使用GetObject(1)可以得到想要的结果。
这就是动态类型,在编译时不会对方法等进行判断,而是在运行时才进行处理,如果调用到不存在的方法才会报错。
C#编译器允许你通过dynamic对象调用任何方法,即使这个方法根本不存在,编译器也不会在编译的时候报编译错误。只有在运行的时候,它才会检查这个对象的实际类型,并检查在它上面Talk()是什么意思。动态类型将使得C#可以以更加统一而便利的形式表示下列对象:
来自动态编程语言——如Python或Ruby——的对象;
通过IDispatch访问的COM对象;
通过反射访问的一般.NET类型;
结构发生过变化的对象——如HTML DOM对象;
当我们得到一个动态类型的对象时,不管它是来自COM还是IronPython、HTML DOM还是反射,只需要对其进行操作即可,动态语言运行时(DLR)会帮我们指出针对特定的对象以及这些操作的具体意义。这将给我们的开发带来极大的灵活性,并且能够极大程度上地精简我们的代码。
动态类型使用注意
不能调用扩展方法;委托与动态类型不能进行隐式转换;
不能调用构造函数和静态方法;
类不能继承dynamic、泛型参数不能使用dynamic和接口实现也不能使用dynamic;
实现动态行为
实现动态行为有3种方法,分别可以用在不同的场合。使用ExpandoObject类
直接使用ExpandoObject类来实现动态行为,代码如下:using System; using System.Dynamic; namespace Study { class Program { static void Main(string[] args) { dynamic obj = new ExpandoObject(); //添加属性 obj.name = "Li Lei"; obj.age = 20; //添加方法 obj.Add = (Func<int, int, int>) ((a, b) => a + b); Console.WriteLine("Name: " + obj.name); Console.WriteLine("Age: " + obj.age); Console.WriteLine("Add: " + obj.Add(100, 123)); Console.Read(); } } }
输出如下:
Name: Li Lei Age: 20 Add: 223
继承DynamicObject类
通过继承DynamicObject类也可以实现动态效果,示例如下:using System; using System.Dynamic; namespace Study { class Program { static void Main(string[] args) { dynamic obj = new MyClass(); obj.name = "Li Lei"; obj.age = 20; obj.CallFunc(); Console.Read(); } } public class MyClass : DynamicObject { public override bool TrySetMember(SetMemberBinder binder, object value) { Console.WriteLine("设置" + binder.Name + "为" + value); return true; } public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { Console.WriteLine("调用" + binder.Name + "方法"); result = null; return true; } } }
输出如下:
设置name为Li Lei 设置age为20 调用CallFunc方法
实现IDynamicMetaObjectProvider接口
如果已经继承了其它的类,则可以通过实现IDynamicMetaObjectProvider接口来实现动态行为,例子如下:using System; using System.Dynamic; using System.Linq.Expressions; namespace Study { class Program { static void Main(string[] args) { dynamic obj = new MyClass(); obj.CallFunc(); Console.Read(); } } public class MyClass : IDynamicMetaObjectProvider { public DynamicMetaObject GetMetaObject(Expression parameter) { Console.WriteLine("获取元数据"); return new MetaDynamic(parameter, this); } } public class MetaDynamic : DynamicMetaObject { public MetaDynamic(Expression expression, object value) : base(expression, BindingRestrictions.Empty, value) { } public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) { MyClass target = base.Value as MyClass; Expression self = Expression.Convert(base.Expression, typeof (MyClass)); var restrictions = BindingRestrictions.GetInstanceRestriction(self, target); Console.WriteLine("调用" + binder.Name + "方法"); return new DynamicMetaObject(self, restrictions); } } }
输出如下:
获取元数据 调用CallFunc方法
相关文章推荐
- C#学习笔记(十):反射
- csharp: Data binding in WPF DataGrid control
- csharp: Data binding in WPF DataGrid control
- csharp: Data binding in WPF DataGrid control
- C#几种截取字符串的方法
- C#基础系列——反射笔记
- C#在winform中调用系统控制台输出
- 【C#】判断文件是否正在被其他进程占用
- c# 同一个文件夹 获取最新修改过的文件
- C#中,实现文件的移动
- 通过XML格式,读取CSV文件
- C# 操作word
- c# TextBox 重绘边框
- C#中string.Format()和ToString()格式化方法
- c#实现动态悬浮窗代码(可用于检测)
- c# equals和==的区别
- 如何解决C#中多个panel重叠问题
- c#控制台应用程序-“进入指定日期检查出星期几”
- 也来说说C#异步委托(转)
- C#委托的介绍(delegate、Action、Func、predicate)(转)