C# 4.0 实现 Method Missing

Method Missing 指在我们调用一个不存在的函数时,系统将此调用转给一个我们定义的函数,一个比较典型的应用是 RoR 中的 find_by 语法:
  1. user = User.find_by_name("tom")
复制代码
C# 4.0 并没有像 Boo 那样直接支持 Method Missing,但是通过动态对象,确实可以做到。我们通过继承 DynamicObject 并 override TryInvokeMember 方法,就可以创建出一个处理不存在的函数的类。以下的代码展示了给 DbEntry 增加动态 find_by 支持的方法:
  1. public class DynamicQuery<T> : System.Dynamic.DynamicObject where T : class, IDbObject
  2. {
  3. public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
  4. {
  5. var ss = binder.Name.Split(new[] { "And" }, StringSplitOptions.None);
  6. if (ss.Length != args.Length)
  7. {
  8. throw new ApplicationException("The args count doesn't match method call " + binder.Name + "");
  9. }
  10. Condition c = null;
  11. for (int i = 0; i < ss.Length; i++)
  12. {
  13. c &= CK.Column[ss] == args;
  14. }
  15. result = DbEntry.Context.GetObject<T>(c);
  16. return true;
  17. }
  18. }
复制代码
上面的代码不是很严谨,比如使用 And 进行 Split,如果字段名是 Andriod,就会出异常,不过,只为 测试是够了,下面是测试代码:
  1. public abstract class User : DbObjectModel<User>
  2. {
  3. public abstract string Name { get; set; }
  4. public abstract int Age { get; set; }

  5. public abstract User Init(string name, int age);

  6. public static dynamic FindBy
  7. {
  8. get { return new DynamicQuery<User>(); }
  9. }
  10. }

  11. class Program
  12. {
  13. static void Main(string[] args)
  14. {
  15. DbEntry.Context.DropAndCreate(typeof(User));
  16. User.New.Init("tom", 18).Save();
  17. User.New.Init("jerry", 99).Save();
  18. User.New.Init("mike", 34).Save();

  19. var u = User.FindBy.Name("tom");
  20. Show(u);
  21. u = User.FindBy.Age(99);
  22. Show(u);
  23. u = User.FindBy.NameAndAge("jerry", 27);
  24. Show(u);
  25. u = User.FindBy.NameAndAge("mike", 34);
  26. Show(u);

  27. Console.WriteLine("The End");
  28. Console.ReadLine();
  29. }

  30. static void Show(dynamic u)
  31. {
  32. if (u == null)
  33. {
  34. Console.WriteLine("<NULL>");
  35. }
  36. else
  37. {
  38. Console.WriteLine("Item: {0},{1},{2}", u.Id, u.Name, u.Age);
  39. }
  40. Console.WriteLine("-------------------------------------");
  41. }
  42. }
复制代码
运行结果:
Item: 1,tom,18
-------------------------------------
Item: 2,jerry,99
-------------------------------------
<NULL>
-------------------------------------
Item: 3,mike,34
-------------------------------------
The End

  和 Boo 的 Method Missing 支持相比,这种方式只能工作在动态对象上,但是我并不希望全盘动态化,所以,这里实现的 FindBy 和字段名之间有一个点,使之看起来不像 Method Missing,倒是有点像连贯 接口,这一点有些不爽,但是毕竟还是提供了以前不可能实现的应用,多了更多的可能性。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值