使用C# 4.0实现动态方法
了解动态语言Ruby的,大概都知道Ruby中有一个很有意思的实例方法叫method_missing。如果在代码中调用一个某个类中不存在的方法,就会调用这个方法。Ruby on Rails中的ActiveRecord利用这个方法,可以提供很方便的动态查询方法,譬如
find_by_name
find_by_username_and_password
find_all_by_first_name_and_last_name
....
细节请参考 http://www.gargoylesoftware.com/RailsDynamicFinders.pdf
当然,通过这个方法,你还可以做许多涉及metaprogramming的东西。
最近发布的C# 4.0 CTP版本引进了大量的动态语言的构造,我们终于也可以很方便地实现动态方法了,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Scripting.Actions;
namespace ConsoleApplication1
{
class Data
{
public int ID { get; set; }
public string Name { get; set; }
public string Value { get;set;}
}
class MyClass : System.Scripting.Actions.Dynamic
{
List<Data> data;
public MyClass()
{
data = new List<Data>{ new Data {ID=1,Name="abc",Value="hello world" },
new Data {ID=2,Name="def",Value="hello joycode"},
};
}
public string Find(int id)
{
if (id <= 0 || id > 2)
throw new ArgumentException("cannot handle this parameter:" + id.ToString());
return Find(d => d.ID == id);
}
public override object Call(CallAction action, params object[] args)
{
if (action.Name == "Find" || action.Name == "FindByID")
return Find((int)args[0]);
else if (action.Name == "FindByName")
return Find(d => d.Name == (string)args[0]);
//当然,在这里,你可以发挥想象力,实现任何你能想到的方法
throw new NotSupportedException();
}
{
Data d = data.Find(p);
if (d == null)
return String.Empty;
return d.Value;
}
}
}
在客户端代码里,你可以这样
dynamic m = new MyClass();
Console.WriteLine(m.Find(1)); //Find方法在类中有声明,但其实还是通过Call方法来调用的
Console.WriteLine(m.FindByID(2)); //但FindByID则没有声明
Console.WriteLine(m.FindByName("def")); //FindByName也没有声明
这里把m声明为dynamic是关键,否则会出错。输出为
hello world
hello joycode
hello joycode
微软的Chris Burrows对此有更深入的讨论:
C# "dynamic," Part II
http://blogs.msdn.com/cburrows/archive/2008/10/28/c-dynamic-part-ii.aspx
posted on 2008-10-31 17:19:55 by saucer 评论(2) 阅读(3350)