8

我正在创建一个类库,可以在多种情况下使用 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 的引用,这是一个缺点。

编辑:我想出了一个我在博客上发布的解决方案 - 请参阅如何同时使库可移植和数据绑定友好?

4

2 回答 2

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等等。

于 2012-07-22T14:14:44.170 回答
3

我认为你的库的低级组件应该提供对这些组件有意义的接口,在那个特定的抽象级别,而不考虑你的 API 的各种消费者可能需要如何调整它们以供自己使用。

例如,如果一个复合 WPF 应用程序将使用您的组件,那么这些应用程序将您的组件封装到一个模型或视图模型中是完全合适的,该模型或视图模型将您的组件提供的IList<T>(或者更好的是)调整为适合绑定到一个看法。IEnumerable<T>ObservableCollection<T>

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

顺便说一句,即使将集合公开为IList<T>. 例如,这允许您的图书馆的消费者在列表中添加和删除项目,这可能不符合界面的精神。

于 2012-07-22T14:17:14.650 回答