dynamic基础类型/C#与动态脚本语言交互/dynamic自定义类型
2015-10-10 10:58
507 查看
ruby python js动态语言有他们自身的优点,因此C#中的var关键字和匿名方法开辟了C#的动态编程路径,.net 4中增加了dynamic类型。
DLR(dynamic language runtime)是脚本运行库,是添加到CLR的一系列服务,它允许添加动态语言,如ruby python,并使C#具有这些动态语言相同的某些动态功能,silverlight也使用DLR。DLR位于System.Dynamic和System.Rumtime.Complier-Services几个类中。
DLR脚本运行库允许给脚本传入变量和从脚本传出变量。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ErrorExample
{
class Program
{
static void Main(string[] args)
{
var staticPerson = new Person();
dynamic dynamicPerson = new Person();
//staticPerson.GetFullName("John", "Smith");//
dynamicPerson.GetFullName("John", "Smith");
// 编译期间不会报错,运行时候才检查报错
}
}
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string GetFullName()
{
return string.Concat(FirstName, " ", LastName);
}
}
}
2. dynamic类型,可以在运行期间改变类型
dynamic dyn;
// 声明为var会报错,var只是编译时候绑定,绑定后就不能变了
dyn = 100;
Console.WriteLine(dyn.GetType());
Console.WriteLine(dyn);
dyn = "This is a string";
Console.WriteLine(dyn.GetType());
Console.WriteLine(dyn);
dyn = new Person() { FirstName = "Bugs", LastName = "Bunny" };
Console.WriteLine(dyn.GetType());
Console.WriteLine("{0} {1}", dyn.FirstName, dyn.LastName);
3.dynamic类型限制
1)不支持拓展方法中使用dynamic类型。
2)匿名函数(lambda表达式)也不能用作动态类型的方法调用的参数。
后台编译时候需要指定运行时期语法语义检查的类来检查,然后生成表达式树,来缓存。显然dynamic类型可以做到动态类型但是是有性能代价的,因为c#本身是静态即时编译类型的语言。
C#中直接使用,从脚本中获取脚本对象,然后给脚本对象传入值,利用脚本对象计算的返回值赋值给C#中变量就可以了。例如:
ScriptRuntime scriptRuntime = ScriptRuntime.CreateFromConfiguration();
dynamic calcRate = scriptRuntime.UseFile("CalcTax.py");
label5.Content = calcRate.CalcTax(Convert.ToDecimal(label5.Content)).ToString();
那么自定义的动态类型,需要继承自DynamicObject或ExpandoObject类。
继承自DynamicObject需要重写了3个方法:
public override bool TryGetMember(GetMemberBinder binder, out object result)
public override bool TrySetMember(SetMemberBinder binder, object value)
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
且这些重载的方法,都是.net帮助调用的,在使用时候只是简单的为类添加属性和方法。
例如:
创建自定义类型对象DynamicObject或ExpandoObject,与基本类型区别。
1.不能创建dynamic的自定义类型的空对象,必须赋予某个继承自DynamicObject或是ExpandoObject类型对象。
2.创建dynamic的自定义类型对象不能一开始赋予给基础类型。
如果需要控制动态对象中的属性的添加和访问,则使该对象派生自DynamicObject是最佳选择。
使用DynamicObject可以重写介个方法,准确的控制对象与运行库的交互方式。其它情况就应该使用ExpandoObject类型,或dynamic基础类型。
DLR(dynamic language runtime)是脚本运行库,是添加到CLR的一系列服务,它允许添加动态语言,如ruby python,并使C#具有这些动态语言相同的某些动态功能,silverlight也使用DLR。DLR位于System.Dynamic和System.Rumtime.Complier-Services几个类中。
DLR脚本运行库允许给脚本传入变量和从脚本传出变量。
一、使用dynamic类型
1.dynamic动态类型,运行时候才会检查动态类型对象及对象上的方法using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ErrorExample
{
class Program
{
static void Main(string[] args)
{
var staticPerson = new Person();
dynamic dynamicPerson = new Person();
//staticPerson.GetFullName("John", "Smith");//
dynamicPerson.GetFullName("John", "Smith");
// 编译期间不会报错,运行时候才检查报错
}
}
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string GetFullName()
{
return string.Concat(FirstName, " ", LastName);
}
}
}
2. dynamic类型,可以在运行期间改变类型
dynamic dyn;
// 声明为var会报错,var只是编译时候绑定,绑定后就不能变了
dyn = 100;
Console.WriteLine(dyn.GetType());
Console.WriteLine(dyn);
dyn = "This is a string";
Console.WriteLine(dyn.GetType());
Console.WriteLine(dyn);
dyn = new Person() { FirstName = "Bugs", LastName = "Bunny" };
Console.WriteLine(dyn.GetType());
Console.WriteLine("{0} {1}", dyn.FirstName, dyn.LastName);
3.dynamic类型限制
1)不支持拓展方法中使用dynamic类型。
2)匿名函数(lambda表达式)也不能用作动态类型的方法调用的参数。
后台编译时候需要指定运行时期语法语义检查的类来检查,然后生成表达式树,来缓存。显然dynamic类型可以做到动态类型但是是有性能代价的,因为c#本身是静态即时编译类型的语言。
二.利用DLR ScriptRuntime和脚本交互
利用系统提供了python,ruby,js类型的脚本语言的 scriptRuntime脚本运行库引擎。C#中直接使用,从脚本中获取脚本对象,然后给脚本对象传入值,利用脚本对象计算的返回值赋值给C#中变量就可以了。例如:
string scrptFile = "CountDisc.py"; ScriptRuntime scriptRuntime = ScriptRuntime.CreateFromConfiguration(); ScriptEngine pythEng = scriptRuntime.GetEngine("Python"); ScriptSource source = pythEng.CreateScriptSourceFromFile(scrptFile); ScriptScope scope = pythEng.CreateScope(); scope.SetVariable("prodCount", Convert.ToInt32(totalItems.Text)); source.Execute(scope); label5.Content = scope.GetVariable("retAmt").ToString();简化调用的实例:
ScriptRuntime scriptRuntime = ScriptRuntime.CreateFromConfiguration();
dynamic calcRate = scriptRuntime.UseFile("CalcTax.py");
label5.Content = calcRate.CalcTax(Convert.ToDecimal(label5.Content)).ToString();
三、定义自己的动态类型-动态添加属性和方法
dynamic修饰的动态类型都是基本类型,如果要修饰自己的动态类型,且动态类型可以动态的添加属性和方法。那么自定义的动态类型,需要继承自DynamicObject或ExpandoObject类。
继承自DynamicObject需要重写了3个方法:
public override bool TryGetMember(GetMemberBinder binder, out object result)
public override bool TrySetMember(SetMemberBinder binder, object value)
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
且这些重载的方法,都是.net帮助调用的,在使用时候只是简单的为类添加属性和方法。
例如:
using System; using System.Dynamic; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; namespace Dynamic { class Program { static void Main(string[] args) { dynamic dyn; dyn = 100; Console.WriteLine(dyn.GetType()); Console.WriteLine(dyn); dyn = "This is a string"; Console.WriteLine(dyn.GetType()); Console.WriteLine(dyn); dyn = new Person() { FirstName = "Bugs", LastName = "Bunny" }; Console.WriteLine(dyn.GetType()); Console.WriteLine("{0} {1}", dyn.FirstName, dyn.LastName); dyn = new WroxDynamicObject(); dyn.FirstName = "Bugs"; dyn.LastName = "Bunny"; Console.WriteLine(dyn.GetType()); Console.WriteLine("{0} {1}", dyn.FirstName, dyn.LastName); dyn.MiddleName = "Rabbit"; Console.WriteLine(dyn.MiddleName); Console.WriteLine(dyn.GetType()); Console.WriteLine("{0} {1} {2}", dyn.FirstName, dyn.MiddleName, dyn.LastName); List<Person> friends = new List<Person>(); friends.Add(new Person() { FirstName = "Daffy", LastName = "Duck" }); friends.Add(new Person() { FirstName = "Porky", LastName = "Pig" }); friends.Add(new Person() { FirstName = "Tweety", LastName = "Bird" }); dyn.Friends = friends; foreach (Person friend in dyn.Friends) { Console.WriteLine("{0} {1}", friend.FirstName, friend.LastName); } Func<DateTime, string> GetTomorrow = today => today.AddDays(1).ToShortDateString(); dyn.GetTomorrowDate = GetTomorrow; Console.WriteLine("Tomorrow is {0}", dyn.GetTomorrowDate(DateTime.Now)); DoExpando(); Console.Read(); } static void DoExpando() { dynamic expObj = new ExpandoObject(); expObj.FirstName = "Daffy"; expObj.LastName = "Duck"; Console.WriteLine(expObj.FirstName + " " + expObj.LastName); Func<DateTime, string> GetTomorrow = today => today.AddDays(1).ToShortDateString(); expObj.GetTomorrowDate = GetTomorrow; Console.WriteLine("Tomorrow is {0}", expObj.GetTomorrowDate(DateTime.Now)); expObj.Friends = new List<Person>(); expObj.Friends.Add(new Person() { FirstName = "Bob", LastName = "Jones" }); expObj.Friends.Add(new Person() { FirstName = "Robert", LastName = "Jones" }); expObj.Friends.Add(new Person() { FirstName = "Bobby", LastName = "Jones" }); foreach (Person friend in expObj.Friends) { Console.WriteLine(friend.FirstName + " " + friend.LastName); } } } class WroxDynamicObject : DynamicObject { Dictionary<string, object> _dynamicData = new Dictionary<string, object>(); public override bool TryGetMember(GetMemberBinder binder, out object result) { bool success = false; result = null; if (_dynamicData.ContainsKey(binder.Name)) { result = _dynamicData[binder.Name]; success = true; } else result = "Property Not Found!"; return success; } public override bool TrySetMember(SetMemberBinder binder, object value) { _dynamicData[binder.Name] = value; return true; } public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { dynamic method = _dynamicData[binder.Name]; result = method((DateTime)args[0]); return result != null; } } }
创建自定义类型对象DynamicObject或ExpandoObject,与基本类型区别。
1.不能创建dynamic的自定义类型的空对象,必须赋予某个继承自DynamicObject或是ExpandoObject类型对象。
2.创建dynamic的自定义类型对象不能一开始赋予给基础类型。
如果需要控制动态对象中的属性的添加和访问,则使该对象派生自DynamicObject是最佳选择。
使用DynamicObject可以重写介个方法,准确的控制对象与运行库的交互方式。其它情况就应该使用ExpandoObject类型,或dynamic基础类型。
相关文章推荐
- 【转】关于c#中委托的解释
- C#生成并引用资源文件
- c# listview 插入数据在第一行显示
- C# 通过Environment 获取 "我的文档"路径
- 在C#代码中应用Log4Net 中配置文件的解释
- c#拓展方法将datatable转换成实体
- C#将dll打包到程序中
- C#基础----Linq之List<T>篇
- C#之结构、枚举和运算符
- C#创建Window Service
- c# wince textbox 选择全部内容
- C# 泛型理解之大白话
- C#高级篇(二)---LINQ、反射、线程
- 【C#】listview应用
- C#网线程里传参数的方法总结
- C#程序(含多个Dll)合并成一个Exe
- 关于C#中的接口
- C# 使用MEF动态加载不同的userControl,并实现不同userControl之间通信
- C# DataRow 比较
- C# DataRow 比较