Dlr2. 关于我
• 江嘉诚 (无厚之刃)
• 华南理工大学
• 微博:@以无厚入有间 ( 典故参见《庄子》)
• 博客:http://sharp-blade.tuita.com/
3. DLR是
• Dynamic Language Runtime
• 由 IronPython 发起人Jim Hugunin开发
• 一个构建在CLR之上的运行时
• 在.Net上构建动态语言的标准体系
The DLR's mission is to enable an ecosystem of
dynamic languages on .NET.
4. 动态语言需要什么
• Lexer & Parser
• 交互式脚本引擎(REPL)
• 动态加载代码的能力
• 动态类型
• 元编程(自省/魔术方法/动态修改类型)
• 其它:Stackless/Actor/Continuation
5. DLR提供了什么
• 脚本语言引擎
• 可以在运行时编译的表达式树
• 延迟绑定
• 动态语言的互操作性
7. ExpressionTree : Hello World
Console.WriteLine(“Hello World”);
using System.Linq.Expressions;
MethodInfo method = typeof (Console)
.GetMethod( "WriteLine", new Type[] { typeof(string) } );
Expression call = Expression.Call(null, method,
Expression.Constant("Hello World")) ;
Action callDelegate = Expression.Lambda<Action>(call).Compile();
callDelegate();
8. ExpressionTree : Binary Expression
3+5
BinaryExpression add = Expression.Add(Expression.Constant(3),
Expression.Constant(5));
Func<int> addDelegate = Expression.Lambda<Func<int>>(add).Compile();
Console.WriteLine("{0}", addDelegate());
9. ExpressionTree : Index Expression
int[] list = { 1, 2, 3 };
list [1] = 4;
int[] list = { 1, 2, 3 };
IndexExpression index = Expression.ArrayAccess(
Expression.Constant(list),
Expression.Constant(1));
Expression indexAccess = Expression.Assign(index,
Expression.Constant(4));
Action indexAccessDelegate =
Expression.Lambda<Action>(indexAccess).Compile();
indexAccessDelegate();
10. ExpressionTree : IfThenElse Expression
if (true) Console.WriteLine("true");
else Console.WriteLine("false");
Expression ifExpression = Expression.IfThenElse(
Expression.Constant(true),
Expression.Call(null,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
Expression.Constant("true")),
Expression.Call(null,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
Expression.Constant("false"))
);
Action ifDelegate = Expression.Lambda<Action>(ifExpression).Compile();
ifDelegate();
11. ExpressionTree : LambdaExpression
Func<int, int, int> add = (x, y) => { return x + y; };
int result = add(3, 5);
Console.WriteLine("result is {0}", result);
ParameterExpression x = Expression.Parameter(typeof(int), "x");
ParameterExpression y = Expression.Parameter(typeof(int), "y");
Expression<Func<int, int, int>> add = Expression
.Lambda<Func<int, int, int>>(Expression.Add(x, y), x, y);
int result = add.Compile()(3, 5);
Console.WriteLine("result is {0}", result);
13. Dynamic & Late Binding
Foo foo = new Foo();
foo.act();
dynamic foo = …… // new Foo()
foo.act();
14. Dynamic语法的绑定过程
dynamic num = 5;
int result = num + 2;
CallSite<Func<CallSite, object, int>> Site1;
CallSite<Func<CallSite, object, int, object>> Site2;
object num = 5;
if (Site1 == null)
{
Site1 = CallSite<Func<CallSite, object, int>>
.Create(
Binder.Convert(
CSharpBinderFlags.None,
typeof(int),
typeof(Program)));
}
15. Dynamic & Late Binding
Func<CallSite, object, int> convert = Site1.Target;
CallSite add = Site1;
if (Site2 == null)
{
Site2 = CallSite<Func<CallSite, object, int, object>>
.Create(
Microsoft.CSharp.RuntimeBinder.Binder.BinaryOperation(
CSharpBinderFlags.None,
ExpressionType.Add,
typeof(Program), ...));
}
int result = convert(add, Site2.Target(Site2, num, 2));
16. Dynamic语法的绑定过程
dynamic num = 5;
int result = num + 2;
CallSite<Func<CallSite, object, int>> Site1;
CallSite<Func<CallSite, object, int, object>> Site2;
object num = 5;
if (Site1 == null) {
Site1 = CallSite<Func<CallSite, object, int>>
.Create(
Binder.Convert(
CSharpBinderFlags.None,
typeof(int),
typeof(Program)));
}
17. Dynamic & Late Binding
Func<CallSite, object, int> convert = Site1.Target;
if (Site2 == null)
{
Site2 = CallSite<Func<CallSite, object, int, object>>
.Create(
Binder.BinaryOperation(
CSharpBinderFlags.None,
ExpressionType.Add,
typeof(Program), ...));
}
int result = convert(Site1, Site2.Target(Site2, num, 2));
19. ExpandoObject
dynamic any = new ExpandoObject();
any.prop = 100;
any.prop = "hello";
any.action = new Func<int>(() => { return 99 + 1; });
Console.WriteLine(any.action());
foreach (var member in (IDictionary<String, Object>)any)
{
Console.WriteLine(member.Key + ": " + member.Value);
}
22. Method Missing
public class AnyDynamicObject : DynamicObject
{
public override bool TryGetMember(GetMemberBinder binder, out object
result)
{
Console.WriteLine("Shit happens,{0}属性被调用了", binder.Name);
result = "no value";
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
Console.WriteLine("Shit happens,{0}属性被赋值了", binder.Name);
return true;
}
}
23. Method Missing
dynamic any = new AnyDynamicObject();
Console.WriteLine(any.name);
any.age = 100;
Shit happens,name属性被调用了
no value
Shit happens,age属性被赋值了
24. 调用Python引擎
example.py :
引用:
def addPrice(x, y): IronPython.dll
return x + y IronPython.Modules.dll
Microsoft.Dynamic.dll
class User(object):
Microsoft.Scripting.dll
def __init__(self, name, email):
self.Name = name
self.AEmail = email
def say(self):
print "hello"
bob = User("bob", "x@gmail.com")
25. 调用Python引擎
ScriptEngine pyEngine =
IronPython.Hosting.Python.CreateEngine();
ScriptScope scope = pyEngine.ExecuteFile("example.py");
Func<dynamic, dynamic, int> add = scope.GetVariable("add");
Console.WriteLine(add(2,5));
dynamic bob = scope.GetVariable("bob");
Console.WriteLine(bob.Name);
bob.say();
7
bob
hello
27. 谁真正需要Dynamic/DLR
• 轻量级ORM
• MSBuild
• 模板引擎
• 解释器/表达式引擎
• 编译正则表达式
• 调用COM
• 替代Reflection.Emit的其它场合
• 构建DSL (Antlr + DLR)