【问题标题】:Bindable LINQ vs. continuous LINQ可绑定 LINQ 与连续 LINQ
【发布时间】:2008-10-03 16:08:00
【问题描述】:

可绑定 LINQ 和连续 LINQ 的主要区别是什么?

•可绑定 LINQ:www.codeplex.com/bindablelinq

•连续 LINQ:www.codeplex.com/clinq

根据提供的反馈又添加了一个项目:

•Obtics:obtics.codeplex.com

【问题讨论】:

  • 不错!我不知道有这样的东西存在。感谢您引起我的注意,亚历克斯。 :-)
  • 这些项目还活着吗?他们迁移到 GitHub 了吗?

标签: bindable-linq


【解决方案1】:

这两个包都试图解决两个问题:缺少 CollectionChanged 事件和动态结果集。还有一个额外的问题可绑定解决,额外的自动事件触发器。


第一个问题这两个软件包旨在解决的是:

LINQ 查询返回的对象 不提供 CollectionChanged 事件。

Continuous LINQ 自动对所有查询执行此操作,没有任何变化:

from item in theSource select item ;

Bindable LINQ 在您将 .asBindable 添加到查询源对象时执行此操作:

from item in theSource.AsBindable() select item ;

第二个问题这两个软件包旨在解决的是:

从 LINQ 查询返回的结果集 是静态的。

通常,当您执行 LINQ 查询时,您的 结果集 不会改变,直到您执行新查询。使用这两个包,您的 result set 会在 source 更新时更新。 (对性能不利,对实时更新有利)

示例

var theSource = new ContinuousCollection<Customer>();
var theResultSet = from item in theSource where item.Age > 25 select item;
//theResultSet.Count would equal 0.

由于您使用 Bindable 或 Continuous LINQ,您可以修改 theSourcetheResultSet 会自动包含新项目。

theSource.Add(new Customer("Bob", "Barker" , 35, Gender.Male)); //Age == 35
//theResultSet.Count would now equal 1.

附加问题 可绑定 LINQ 提供:(直接从他们自己的页面引用)

contactsListBox.ItemsSource = from c in customers
                              where c.Name.StartsWith(textBox1.Text)
                              select c;

可绑定 LINQ 将检测到 查询依赖于 Text 属性 TextBox 对象,textBox1。自从 TextBox 是一个 WPF 控件,可绑定 LINQ 知道订阅 控件上的 TextChanged 事件。

最终结果是作为用户 类型,查询中的项目是 重新评估,变化出现在 屏幕。不需要额外的代码 处理事件。

【讨论】:

    【解决方案2】:

    我可以提请您注意另一个 codeplex 项目吗?它被称为 Obtics 并处理相同的问题 (http://obtics.codeplex.com)。

    它解决了第一个问题和第二个问题以及其他问题,并将反应性提高到了非常深的水平(具有基于 LINQ 的光线追踪器的演示)。

    它声称完全支持所有 LINQ 语句和 Enumerable 类的方法。

    它使用另一种机制来创建实时查询:

    var theResultSet = ExpressionObserver.Execute(
        () => from item in theSource where item.Age > 25 select item
    ).Cascade();
    

    【讨论】:

    • 我刚试了一下,似乎重新评估 theResultSet 会导致 theSource 被重新枚举,所以它没有解决上面描述的第二个问题。我想我的方法可能是错误的......
    【解决方案3】:

    确实; Continuous LINQ 的主要问题是无法使用任何实现通用 IEnumerable 和 INotifyCollectionChanged 的​​集合。可绑定 LINQ 使用实现这两个接口的自定义集合没有问题。

    【讨论】:

      【解决方案4】:

      要记住的另一件事是,虽然 BindableLinq 需要在 LINQ 语句中调用“.AsBindable()”,但 CLINQ 要求您使用 ContinuousCollection 而不是 ObservableCollection。在简单地看了两者之后,我想我会使用可绑定的 LINQ。

      【讨论】:

        【解决方案5】:

        使用可绑定 LINQ,因为它实现了 IDisposable,因此您可以控制何时释放查询。当你处理它时,所有对 INotifyPropertyChanged 的​​订阅都会取消订阅。

        Continuous LINQ 应该通过弱事件来解决这个问题,但就我能够测试的情况而言,它不起作用。

        嗯...这似乎是可绑定 LINQ 的问题(第二个断言失败):

        var _source = CreateSource_6People(); //(David, 27), (Mark, 15), (Steve, 30), (Jordan, 43), (Shiva, 30), (Erb, 43)
        IBindable<int> bindable = _source.AsBindable().Sum(x => x.Age);
        var agesSum = 27+15+30+43+30+43;
        Assert.AreEqual(agesSum, bindable.Current); //PASSES
        
        _source[0].Age += 1;
        Assert.AreEqual(agesSum + 1, bindable.Current); //FAILS... DISAPPOINTING
        

        【讨论】:

          【解决方案6】:

          我认为可绑定 LINQ 和连续 LINQ 大致相同:它们提供对 LINQ 计算变化的观察。提供的实现和 API 可能有所不同。我的ObservableComputations 库似乎涵盖了 Bindable LINQ 和连续 LINQ 所期望的功能,并且在https://stackoverflow.com/a/174924/2663791 中没有提到任何问题。该库与INotifyPropertyChangedINotifyCollectionChanged 接口一起使用,这使得可以直接使用ObservableCollection 进行操作。 使用该库,您可以编写如下代码:

          using System;
          using System.Collections.ObjectModel;
          using System.ComponentModel;
          using System.Linq;
          using IBCode.ObservableComputations;
          
          namespace ObservableComputationsExamples
          {
              public class Order : INotifyPropertyChanged
              {
                  public event PropertyChangedEventHandler PropertyChanged;
          
                  public int Num {get; set;}
          
                  private decimal _price;
                  public decimal Price
                  {
                      get => _price;
                      set
                      {
                          _price = value;
                          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Price)));
                      }
                  }
          
                  public Order(int num, decimal price)
                  {
                      Num = num;
                      _price = price;
                  }
              }
          
              class Program
              {
                  static void Main(string[] args)
                  {
                      ObservableCollection<Order> orders = 
                          new ObservableCollection<Order>(new []
                          {
                              new Order(1, 15),
                              new Order(2, 15),
                              new Order(3, 25),
                              new Order(4, 27),
                              new Order(5, 30),
                              new Order(6, 75),
                              new Order(7, 80),
                          });
          
                      //********************************************
                      // We start using ObservableComputations here!
                      Filtering<Order> expensiveOrders = orders.Filtering(o => o.Price > 25); 
          
                      checkFiltering(orders, expensiveOrders); // Prints "True"
          
                      expensiveOrders.CollectionChanged += (sender, eventArgs) =>
                      {
                          // see the changes (add, remove, replace, move, reset) here
                      };
          
                      // Start the changing...
                      orders.Add(new Order(8, 30));
                      orders.Add(new Order(9, 10));
                      orders[0].Price = 60;
                      orders[4].Price = 10;
                      orders.Move(5, 1);
                      orders[1] = new Order(10, 17);
          
                      checkFiltering(orders, expensiveOrders); // Prints "True"
          
                      Console.ReadLine();
                  }
          
                  static void checkFiltering(
                      ObservableCollection<Order> orders, 
                      Filtering<Order> expensiveOrders)
                  {
                      Console.WriteLine(expensiveOrders.SequenceEqual(
                          orders.Where(o => o.Price > 25)));
                  }
              }
          }
          

          请将ObservableComputations 库添加到问题的列表中(在 Obtics 之后)。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2010-12-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-12-17
            相关资源
            最近更新 更多