C#类库集合ObservableCollection <t> vs Collection <t> </t> </t>

时间:2012-07-22 14:08:19

标签: c# .net wpf silverlight

我正在创建一个类库,可以在很多情况下用于ASP.NET,控制台应用程序,其他类库和XAML目标,如Silverlight或WPF。

最初我决定将集合公开为IList。但是当使用XAML编写样本时,我发现如果我想让它很容易绑定到这些集合,我需要使用ObservableCollection。

我有什么选择?

我可以让库暴露ObservableCollection并强制对与XAML无关的用户。这是件坏事吗?

我可以使我的类通用,允许调用者指定他们想要的集合类型,只要它实现ICollection,可能默认为Collection

我可以创建一组使用ObservableCollection的类和一组不使用Foo和ObservableFoo的类。

我可以在我的类中实现INotifyCollectionChanged但是当ObservableCollection为我做这件事时,这似乎很愚蠢。

显然,我正在努力保持代码干净简单,但支持数据绑定似乎很重要。

有什么建议吗?

编辑:尝试使用两种替代方法创建可移植类库项目。

在Foo课堂上我有

    private readonly Collection<string> strings = new Collection<string>();

    public ReadOnlyCollection<string> Strings
    {
        get
        {
            return new ReadOnlyCollection<string>(this.strings);
        }
    }

在班级ObservableFoo中我有

    private readonly ObservableCollection<string> strings = new ObservableCollection<string>();

    public ReadOnlyObservableCollection<string> Strings
    {
        get
        {
            return new ReadOnlyObservableCollection<string>(this.strings);
        }
    }

非常简单的单元测试代码是

    [TestMethod]
    public void TestMethod1()
    {
        var foo = new ObservableFoo(); // or new Foo()

        Assert.AreNotEqual(0, foo.Id);
        Assert.AreNotEqual(0, foo.Strings.Count);
    }

唯一的缺点是,当我使用ReadOnlyObservableCollection时,测试项目得到了这个编译错误

  

类型   'System.Collections.ObjectModel.ReadOnlyObservableCollection`1'是   在未引用的程序集中定义。你必须添加一个   参考程序集'System.Windows,Version = 2.0.5.0,   Culture = neutral,PublicKeyToken = 7cec85d7bea7798e,Retargetable = Yes'

因此,在这种情况下,使用ReadOnlyObservableCollection将强制用户添加对System.Windows的引用,这是一个缺点。

编辑:我想出了一个我在博客上发布的解决方案 - 请参阅How to make a library portable and data binding friendly at the same time?

2 个答案:

答案 0 :(得分:3)

嗯,这取决于。如果您正在编写纯模型库,那么公开WPF特定的接口是没有意义的;这将迫使用户链接WPF库,即使他们不需要。即使它不是,它暴露了用户不需要的东西,这不是一个好的设计恕我直言。

如果您的库不限于模型使用,我会将其分为几个部分:所有使用场景所需的核心,具有WPF特定接口的WPF相关部分,也许具有ASP特定功能的ASP特定部分等等上。用户将挑选他们需要的部件并使用它们。


编辑:正如@ Julien的评论所述,ObservableCollection<T>现在已成为核心的一部分,因此包括它不会让用户依赖于WPF特定的库。不过,这个想法保持不变。对于WPF用法,您经常需要提供/使用特定功能(ObservableCollectionINotifyPropertyChanged / DependencyObject,依赖项属性,仅在UI线程中的通知等等。这意味着它们属于项目中特定于WPF的单独部分。

因此,您可以使库包含几个部分:Library.Core.dll包含通用/模型开发所需的函数,Library.WPF.dll处理WPF特定的东西并使用Library.Core.dll,也许是Library。 Console.dll和Library.ASP.dll也是如此。 WPF的用户将使用Library.Core.dll和Library.WPF.dll,控制台程序可能需要Library.Core.dll和Library.Console.dll等。

答案 1 :(得分:3)

我认为库的低级组件应提供在特定抽象级别对这些组件有意义的接口,而不考虑API的各种使用者如何根据自己的需要调整它们

例如,如果复合WPF应用程序将使用您的组件,那么将这些组件封装到适应IList<T>的模型或视图模型(或更好的{{1}中)将完全适合这些应用程序。您的组件提供的IEnumerable<T>适合绑定到视图。

控制台应用程序可能不需要这样的开销,并且可以愉快地使用ObservableCollection<T>

另外,即使将集合公开为IEnumerable<T>,也要小心。这允许您的库的使用者添加和删除列表中的项目,例如,这可能不符合界面的精神。