dynamic基础类型C#与动态脚本语⾔交互dynamic⾃定义类型ruby python js动态语⾔有他们⾃⾝的优点,因此C#中的var关键字和匿名⽅法开辟了C#的动态编程路径, 4中增加了dynamic类型。
DLR(dynamic language runtime)是脚本运⾏库,是添加到CLR的⼀系列服务,它允许添加动态语⾔,如ruby python,并使C#具有这些动态语⾔相同的某些动态功能,silverlight也使⽤DLR。DLR位于System.Dynamic和System.Rumtime.Complier-Services⼏个类中。
DLR脚本运⾏库允许给脚本传⼊变量和从脚本传出变量。
⼀、使⽤dynamic类型
writeline使用方法python1.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)
且这些重载的⽅法,都是帮助调⽤的,在使⽤时候只是简单的为类添加属性和⽅法。
例如:
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" };
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];
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基础类型。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。