如何实现可用于不同类型对象的功能?

时间:2012-07-19 08:49:17

标签: c# oop design-patterns

我必须在我的应用程序中实现'全局'搜索/过滤功能。每个包含信息列表的窗口,无论是DataGrid还是列表的其他实现,都必须有一个搜索框,如果用户在搜索框中输入文本,它将按搜索的内容过滤该列表。我只想实现一次搜索逻辑。

在大多数情况下,这不一定太难。原因是大多数包含列表的窗口将基于相同的数据类型。这些都是ViewModel,每个ViewModel都扩展了ViewModelBase,而ViewModelBase包含了我将要搜索的数据。

一个基本的例子:

public class ZoneVm : ViewModelBase
{
    // Zone specific functionality
}

public class UserVm : ViewModelBase
{
    // User specific functionality
}

public class ViewModelBase : INotifyPropertyChanged
{
    public string Name { get; set; }
    public int Value { get; set; }

    // The handy thing about the common view model base is that 
    // I can contain the model binding in a single place

    // It will be easy to search List<ZoneVm> and List<UserVm> because
    // they are both effectively List<ViewModelBase>. 
}

难点在于我必须搜索的异常值对象。有些窗口包含扩展ViewModelBase的对象列表,因此我不会有这个可预测的属性列表来搜索,例如。

public class PanelData // doesn't implement ViewModelBase :-(
{
    public int SerialNumber { get; set; }
    public Customer Customer { get; set; }

    // other properties that I'll have to search/filter on
}

这种任务是否有“最佳实践”方法?有设计模式可以解决这个问题吗?我应该如何搜索/过滤2种(可能更多)不同种类的列表?

3 个答案:

答案 0 :(得分:0)

我的建议是创建一个接口而不是基类,即IViewModelBase。此接口可以为空。另外,创建你的基类,但它只针对某些对象(并且它也是抽象的)。

public interface IViewModelBase : INotifyPropertyChanged
{
}

public abstract class Vm : IViewModelBase 
{
        public string Name { get; set; }
        public int Value { get; set; }
        public event PropertyChangedEventHandler PropertyChanged;
}

public class ZoneVm : Vm
{
    // Zone specific functionality
}

public class UserVm : Vm
{
    // User specific functionality
}

public class PanelData : IViewModelBase
{
    public int SerialNumber { get; set; }
    public Customer Customer { get; set; }
    public event PropertyChangedEventHandler PropertyChanged;
}

答案 1 :(得分:0)

我认为您不希望每个数据都有一个共同的可搜索成员? (这可以通过使用与这个抽象成员的公共IData接口来进行处理,如Ofer所说)

我会将它们放在可查询的集合中并以抽象的方式实现搜索(请自行填写空白):

class MySearchableDataListBase<T> : INotifyPropertyChanged
{
   List<T> _list = new List<T>();
   string _currentFilterString = "";

   abstract bool FilterItemPredicate(T item, string query);

   public abstract IEnumerable<T> FilteredItems
   {
      get {
         return _list.Where(i => FilterItemPredicate(i, _currentFilterString)).ToArray();
      }
   }

   public string FilterQuery
   {
      get { return _currentFilterString; }
      set {
         if (value != _currentFilterString)
         {
             _currentFilterString = value;
             OnPropertyChanged("FilterQuery");
             OnPropertyChanged("FilteredItems");
         }
      }
   }
}

然后,您可以将其用作数据的集合,并为过滤/搜索提供命令和属性。

答案 2 :(得分:0)

您可能需要查看mixins:re - mix

它允许您混合对象中的功能(这有点像多继承) 然后,您可以提供接口实现,例如,具有继承Window的类,并具有ViewModelBase的方法/属性,可通过接口获得。