C # Class Library Collections ObservableCollection <T> vs Collection <T>

I am creating a class library that can be used in several ASP.NET, Console Apps situations, other class libraries, and XAML objects such as Silverlight or WPF.

At first I decided to expose collections as IList. But then, when I write samples using XAML, I found that if I want to simplify the binding to these collections, I need to use an ObservableCollection.

What are my options?

I could make the library publicize the ObservableCollection and force it to be used by users who have nothing to do with XAML. This is bad?

I could create my own generic class, letting the caller specify the type of collection they want if it implements ICollection, possibly the default for Collection

I could create a set of classes that uses an ObservableCollection, and one that doesn't say Foo and ObservableFoo.

I could implement INotifyCollectionChanged in my class, but that seems dumb when ObservableCollection does it for me.

Obviously, I try to keep the code clean and simple, but data binding support seems important.

Any suggestions?

Edit: tried to create a portable class library project using both alternatives.

In the Foo class, I have

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

In the class ObservableFoo I have

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

The simplest unit test code

  [TestMethod] public void TestMethod1() { var foo = new ObservableFoo(); // or new Foo() Assert.AreNotEqual(0, foo.Id); Assert.AreNotEqual(0, foo.Strings.Count); } 

The only drawback is that when I used ReadOnlyObservableCollection, the test project received this compilation error

The type 'System.Collections.ObjectModel.ReadOnlyObservableCollection`1' is defined in an assembly that is not referenced. You must add a reference to the assembly 'System.Windows, Version = 2.0.5.0, Culture = Neutral, PublicKeyToken = 7cec85d7bea7798e, Retargetable = Yes'

Therefore, in this case, using ReadOnlyObservableCollection will force users to add a link to System.Windows, which is a drawback.

Edit: I came up with a solution that I posted on my blog - see How to make the library portable and data binding friendly at the same time?

+8
c # wpf silverlight
source share
2 answers

Well, it depends. If you are writing a clean library of models, it makes no sense to reveal WPF-specific interfaces; this will force users to link to the WPF libraries, even if they don’t need it. Even if it is not, it provides something that users will not need, which is not a good IMHO design.

If your library is not limited to using the model, I would divide it into several parts: the kernel, which is necessary for all use cases, the WPF-dependent part with WPF-specific interfaces, possibly the ASP-specific part, with ASP-specific functions, and therefore on. Users will select the details they need and use them.


Edit: as pointed out by @Julien's comments, ObservableCollection<T> now part of the kernel, so enabling it will not depend on WPF-dependent libraries. However, the idea remains the same. To use WPF, you often need to offer / work with certain functions ( ObservableCollection , INotifyPropertyChanged / DependencyObject , dependency properties, notifications only in the user interface thread, etc.). This means that they relate to a separate, WPF-specific part of the project.

Thus, you can make a library consisting of several parts: Library.Core.dll, containing functions necessary for the development of common / models, Library.WPF.dll, associated with specific WPF files and using Library.Core.dll, possibly Library . Console.dll and Library.ASP.dll. WPF users will use Library.Core.dll and Library.WPF.dll, console programs may need Library.Core.dll and Library.Console.dll, etc.

+3
source share

I think that the low-level components of your library should offer interfaces that make sense for these components at this particular level of abstraction, regardless of how different consumers of your API may need to adapt them for their own use.

For example, if a composite WPF application will use your components, it would be perfectly advisable for these applications to encapsulate your components in a model or view model that adapts the proposed IList<T> (or even better, IEnumerable<T> ) your components in an ObservableCollection<T> , suitable for binding to representation.

The console application may not need such overhead and may happily use IEnumerable<T> .

Aside, be careful even if you expose collections as IList<T> . This allows users of your library to add and remove items from the list, for example, which may not be in the style of the interface.

+3
source share

All Articles