代码之家  ›  专栏  ›  技术社区  ›  mpen

如何设计我的C#jQuery API,使其使用起来不混乱?

  •  5
  • mpen  · 技术社区  · 14 年前

    making a jquery clone 对于C#。现在我已经设置好了,所以每个方法都是 IEnumerable<HtmlNode> 所以它与已经使用的现有项目很好地配合使用。 HtmlAgilityPack .andSelf .end 从内部堆栈中“弹出”最近匹配的元素。如果我更改类,使其始终在SharpQuery对象(而不是可枚举对象)上运行,我可以模拟此功能,但仍然存在问题。

    $('xxx') 实际上,您正在创建一个新的jQuery对象,并从一个空堆栈开始刷新。在C#中,您不想这样做,因为您不想从web重新加载/重新提取文档。因此,您可以将其加载到SharpQuery对象或HtmlNodes列表中(只需要DocumentNode开始)。

    在jQuery文档中,他们给出了这个示例

    $('ul.first').find('.foo')
      .css('background-color', 'red')
    .end().find('.bar')
      .css('background-color', 'green')
    .end();
    

    () 接线员,你就从 sq.Find() 相反,它在文档的根上操作,本质上做同样的事情。但是人们会尝试写 在一条线上,然后 平方查找()

    所以。。。我应该如何设计我的API?我要再加一个吗 Init 方法,所有查询都应以该方法开始,该方法重置堆栈(但如何强制它们以该方法开始?),或添加 Reset() [] 而是告诉他们从那开始?我是不是说“算了,反正没人用那些状态保持的函数?”

    基本上,您希望jQuery示例如何用C#编写?

    1. sq["ul.first"].Find(".foo") ...
      失败:滥用 [] 财产。

    2. sq.Init("ul.first").Find(".foo") ...
      缺点:没有什么能真正迫使程序员从Init开始,除非我添加了一些奇怪的“初始化”机制;用户可以尝试从 .Find 却没有得到他期待的结果。也, Find 基本上是一样的,只是前者也会重置堆栈。

    3. sq.Find("ul.first").Find(".foo") ... .ClearStack()
      失败:程序员可能会忘记清除堆栈。


    4. end() 未实施。

    5. 使用两个不同的对象。
      HtmlDocument 作为所有查询开始的基础,然后每个方法都返回 SharpQuery HtmlDocument文件 始终保持初始状态,但是 对象可能具有不同的状态。不幸的是,这意味着我必须两次实现一堆东西(一次用于HtmlDocument,一次用于SharpQuery对象)。

    6. new SharpQuery(sq).Find("ul.first").Find(".foo") ...
      构造函数复制对文档的引用,但重置堆栈。

    2 回复  |  直到 14 年前
        1
  •  4
  •   kevingessner    14 年前

    我认为你在这里遇到的主要障碍是你想摆脱一个 SharpQuery 每个文档的对象。jQuery不是这样工作的;一般来说,jQuery对象是不可变的。当调用更改元素集的方法时(如 find end add

    var theBody = $('body');
    // $('body')[0] is the <body>
    theBody.find('div').text('This is a div');
    // $('body')[0] is still the <body>
    

    (见 documentation of end 更多信息)

    SharpQuery应该以同样的方式操作。使用文档创建SharpQuery对象后,方法调用应返回new 夏普查询

    var sq = SharpQuery.Load(new Uri("http://api.jquery.com/category/selectors/"));
    var header = sq.Find("h1"); // doesn't change sq
    var allTheLinks = sq.Find(".title-link") // all .title-link in the whole document; also doesn't change sq
    var someOfTheLinks = header.Find(".title-link"); // just the .title-link in the <h1>; again, doesn't change sq or header
    

    这种方法有几个好处。因为 sq , header , allTheLinks 夏普查询 反对该文件(例如 allTheLinks.text("foo") , someOfTheLinks.text() == "foo" .).

    实施 其他基于堆栈的操作也变得很容易。当每个方法创建一个新的、过滤的 夏普查询 对象,它保留对该父对象的引用( 所有的链接 , 平方 结束 简单到只需返回一个新的 夏普查询 包含与父元素相同的元素,例如:

    public SharpQuery end()
    {
        return new SharpQuery(this.parent.GetAllElements());
    }
    

    (或者不管你的语法如何变化。)

    我认为这种方法将使您获得最类似jQuery的行为,并且实现起来相当简单。我一定会关注这个项目的,这是个好主意。

        2
  •  0
  •   Samuel Neff    14 年前

    我倾向于选择2的变体。在jQuery$()中是一个函数调用。C没有全局函数,静态函数调用是最接近的。我将使用一个方法来指示您正在创建类似。。

    SharpQuery.Create("ul.first").Find(".foo")