WEB开发网
开发学院软件开发C语言 C# 4.0 实现 Method Missing 阅读

C# 4.0 实现 Method Missing

 2010-09-30 22:37:57 来源:WEB开发网   
核心提示:Method Missing 指在我们调用一个不存在的函数时,系统将此调用转给一个我们定义的函数,C# 4.0 实现 Method Missing,一个比较典型的应用是 RoR 中的 find_by 语法: user=User.find_by_name("tom")C# 4.0 并没有像 Boo 那

Method Missing 指在我们调用一个不存在的函数时,系统将此调用转给一个我们定义的函数,一个比较典型的应用是 RoR 中的 find_by 语法:

user = User.find_by_name("tom")

C# 4.0 并没有像 Boo 那样直接支持 Method Missing,但是通过动态对象,确实可以做到。我们通过继承 DynamicObject 并 override TryInvokeMember 方法,就可以创建出一个处理不存在的函数的类。以下的代码展示了给 DbEntry 增加动态 find_by 支持的方法:

public class DynamicQuery<T> : System.Dynamic.DynamicObject where T : class, IDbObject
{
  public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
  {
    var ss = binder.Name.Split(new[] { "And" }, StringSplitOptions.None);
    if (ss.Length != args.Length)
    {
      throw new ApplicationException("The args count doesn't match method call " + binder.Name + "");
    }
    Condition c = null;
    for (int i = 0; i < ss.Length; i++)
    {
      c &= CK.Column[ss[i]] == args[i];
    }
    result = DbEntry.Context.GetObject<T>(c);
    return true;
  }
}

上面的代码不是很严谨,比如使用 And 进行 Split,如果字段名是 Andriod,就会出异常,不过,只为测试是够了,下面是测试代码:

public abstract class User : DbObjectModel<User>
{
  public abstract string Name { get; set; }
  public abstract int Age { get; set; }
  public abstract User Init(string name, int age);
  public static dynamic FindBy
  {
    get { return new DynamicQuery<User>(); }
  }
}
class Program
{
  static void Main(string[] args)
  {
    DbEntry.Context.DropAndCreate(typeof(User));
    User.New.Init("tom", 18).Save();
    User.New.Init("jerry", 99).Save();
    User.New.Init("mike", 34).Save();
    var u = User.FindBy.Name("tom");
    Show(u);
    u = User.FindBy.Age(99);
    Show(u);
    u = User.FindBy.NameAndAge("jerry", 27);
    Show(u);
    u = User.FindBy.NameAndAge("mike", 34);
    Show(u);
    Console.WriteLine("The End");
    Console.ReadLine();
  }
  static void Show(dynamic u)
  {
    if (u == null)
    {
      Console.WriteLine("<NULL>");
    }
    else
    {
      Console.WriteLine("Item: {0},{1},{2}", u.Id, u.Name, u.Age);
    }
    Console.WriteLine("-------------------------------------");
  }
}

运行结果:

Item: 1,tom,18
-------------------------------------
Item: 2,jerry,99
-------------------------------------
<NULL>
-------------------------------------
Item: 3,mike,34
-------------------------------------
The End

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

Tags:实现 Method Missing

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接