Observable collections broken by trunk

30 views
Skip to first unread message

HappyNomad

unread,
Nov 26, 2008, 5:17:16 AM11/26/08
to nhibernate-development
Observable collections are an integral part of .NET 3.x and WPF in
particular. Last year I added support for observable collections by
using NH's custom collections API, and made the solution available
here:
http://happynomad121.blogspot.com/2007/12/collections-for-wpf-and-nhibernate.html
All that work took me a month, but it was worth it since it's been
helping a lot of people use WPF together with NH.

When I tried compiling my ObservableCollections project against the
trunk just now, however, I got some unsettling compiler warnings/
errors. Looking at the source code for PersistentGenericList, etc. I
can see the breaking changes made since NH v2.0.1.GA. That is,
all .NET collection interface members were made to be explicitly
implemented. The problem with that, is that I cannot override them
then call their original implementations from my
PersistentObservableList, etc. subclasses.

Afaik, this problem must be solved within the NH sources. What I
would like to do, is add this template method to
AbstractPersistentCollection:
protected abstract void OnCollectionChanged
( NotifyCollectionChangedAction action, object changedItem, int
index );
and then call it from all of its subclasses, whenever the collection's
contents are modified. Just look at my ObservableCollections project
to see how this method's parameters are determined for each collection
and modification type.

We could even take this one step further by implementing
INotifyCollectionChanged on AbstractPersistentCollection. That
interface contains just one member: CollectionChanged. In that case,
I could also provide an implementation for OnCollectionChanged.

I can undertake this task myself, if I've been assured that the patch
I create will be committed once I've finished.

Fabio Maulo

unread,
Nov 26, 2008, 7:12:09 AM11/26/08
to nhibernate-...@googlegroups.com
The public API is IUserCollectionType

2008/11/26 HappyNomad <happyn...@gmail.com>



--
Fabio Maulo

HappyNomad

unread,
Nov 26, 2008, 9:18:54 AM11/26/08
to nhibernate-development
If you look at my ObservableCollections project, you will see that I
am intimately familiar with IUserCollectionType. And I will continue
using that API even with the changes I am suggesting. As I wrote in
my above post, however, the problem now is that the breaking changes
in NH 2.1 are making it impossible to intercept all modification
operations on persistent collections. NH 2.1 targets .NET 3.5, and
observability is a fundamental feature of .NET 3.x, so I think the
best way to solve this problem is to incorporate observability into
the NH core.


On Nov 26, 7:12 pm, "Fabio Maulo" <fabioma...@gmail.com> wrote:
> The public API is IUserCollectionType
>
>
> 2008/11/26 HappyNomad <happynomad...@gmail.com>
> > Observable collections are an integral part of .NET 3.x and WPF in
> > particular.  Last year I added support for observable collections by
> > using NH's custom collections API, and made the solution available
> > here:
>
> >http://happynomad121.blogspot.com/2007/12/collections-for-wpf-and-nhi...

Fabio Maulo

unread,
Nov 26, 2008, 9:29:55 AM11/26/08
to nhibernate-...@googlegroups.com
2008/11/26 HappyNomad <happyn...@gmail.com>


 NH 2.1 targets .NET 3.5, and
observability is a fundamental feature of .NET 3.x, so I think the
best way to solve this problem is to incorporate observability into
the NH core.
 
Sure... and sure we will add INotifyProperyChanged, and a base class to work with lazy-loading and INotifyCollectionChanged and probably IBindingList implementation.
Be sure about that.
--
Fabio Maulo

Tuna Toksöz

unread,
Nov 26, 2008, 9:30:54 AM11/26/08
to nhibernate-...@googlegroups.com
ups.
--
Tuna Toksöz
http://www.tunatoksoz.com

Typos included to enhance the readers attention!

Gustavo Ringel

unread,
Nov 26, 2008, 9:33:51 AM11/26/08
to nhibernate-...@googlegroups.com
I think the task of the persistence layer is not to be bindable to an specific UI model...or to inform about something to an specific UI model.
So for sure it is not part of the core.
It may be an extension to put in the contributions...

Gustavo.

On Wed, Nov 26, 2008 at 4:29 PM, Fabio Maulo <fabio...@gmail.com> wrote:

HappyNomad

unread,
Nov 26, 2008, 9:42:13 AM11/26/08
to nhibernate-development
Well, do you want me to create a patch? I and many other users are
using NH with WPF which REQUIRES all collections to be observable. In
order for us to be able to use the trunk, the bare minimum is add this
template method to AbstractPersistentCollection:
protected abstract void OnCollectionChanged
( NotifyCollectionChangedAction action, object changedItem, int
index );
and then call it from all of its subclasses, whenever the collection's
contents are modified. With that in place, then I could take care of
the rest in my updated ObservableCollections project. Making that
change to AbstractPersistentCollection would not in any way adversely
affect other uses of persistent collections.


On Nov 26, 9:29 pm, "Fabio Maulo" <fabioma...@gmail.com> wrote:
> 2008/11/26 HappyNomad <happynomad...@gmail.com>

Stephen Bohlen

unread,
Nov 26, 2008, 9:43:55 AM11/26/08
to nhibernate-...@googlegroups.com
Its also true that this is actually a bit more complex that is being suggested here.  .NET 3.5 actually support two completely different 'notify-property-change' and 'notify-collection-change' eventing model -- one for WinForms and another for WPF.  The suggestion being offered here seems to be solely WPF-centric and will (perhaps) meet the needs of WPF-adopters but won't address the needs of the winforms/webforms crowd.
 
I (personally) think it makes more sense for the NHib core to be extensible and overridable rather than to explicitly support the eventing model of any one single UI technology.  If there are changes that need to be made to support this approach, then I think they make sense (to me) but to chase the specific implementation of any one eventing model of any one UI platform is a losing battle (IMHO), especially since MS has at least three *current* UI platforms that would have to be explicitly supported (winforms, webforms, and WPF).
 
For some detail on exactly how complex (and differing) the the notify-changes-to-object-via-event-raising model is between these UI platforms, I would invite anyone to read Rocky Lhotka's most-recent book on his changes to CSLA to support the different platforms (although I am not a great big fan of CSLA per-se, reading his books on it offer some fascinating insight into the nuances of parts of the ,NET fx).
 
-Steve B.

Fabio Maulo

unread,
Nov 26, 2008, 9:51:06 AM11/26/08
to nhibernate-...@googlegroups.com
Rocky rocks!!! even if he are using too "fat" BO.

2008/11/26 Stephen Bohlen <sbo...@gmail.com>



--
Fabio Maulo

HappyNomad

unread,
Nov 26, 2008, 9:54:31 AM11/26/08
to nhibernate-development
I would like to point out that NH 2.1 itself targets .NET 3.5. And
INotifyCollectionChanged is part of .NET 3.5. INotifyPropertyChanged
and INotifyCollectionChanged is a general mechanism in .NET for making
objects observable. It is NOT part of a "specific UI model". Sure,
WPF uses these interfaces, but it could be used for other GUI
frameworks as well. It could even be used for non-GUI frameworks
which observe the domain model.

In any case, the bare minimum I am asking at the moment is add this
template method to AbstractPersistentCollection:
protected abstract void OnCollectionChanged
( NotifyCollectionChangedAction action, object changedItem, int
index );
and then call it from all of its subclasses, whenever the collection's
contents are modified. This wouldn't be adding observability per se
(although it's not far from it I admit).


On Nov 26, 9:33 pm, "Gustavo Ringel" <gustavo.rin...@gmail.com> wrote:
> I think the task of the persistence layer is not to be bindable to an
> specific UI model...or to inform about something to an specific UI model.
> So for sure it is not part of the core.
> It may be an extension to put in the contributions...
>
> Gustavo.
>
> On Wed, Nov 26, 2008 at 4:29 PM, Fabio Maulo <fabioma...@gmail.com> wrote:
> > 2008/11/26 HappyNomad <happynomad...@gmail.com>
>

Stephen Bohlen

unread,
Nov 26, 2008, 9:54:55 AM11/26/08
to nhibernate-...@googlegroups.com
OT: indeed, I can respect what he's doing and how he's doing it even as I disagree with the underlying value system atop which his work sits
 
For anyone doing business objects in a real-world context, looking at how he solves the same challenges we all face can be valuable.

32A.png

Davy Brion

unread,
Nov 26, 2008, 10:01:20 AM11/26/08
to nhibernate-...@googlegroups.com
last i checked, the trunk targets .NET 2.0

there was a thread about just a few days ago:
http://groups.google.com/group/nhibernate-development/browse_thread/thread/73d9634269dbcd7b

Stephen Bohlen

unread,
Nov 26, 2008, 10:03:12 AM11/26/08
to nhibernate-...@googlegroups.com
Actually, if you look really closely you will see that...
 
1) yes, .NET 3.5 supports these interfaces for change notification
2) under 3.5 there are DIFFERENT notification interfaces that you need to implement to properly participate in WPF than in winforms (the source of my statement that several of these are 'UI specific'
 
If you are building your own UI in a technology of your own design, then you can choose which of the notification interfaces you are interested in implementing in your objects and (presumably) your own UI technology would be able to similarly 'choose' which of these events to subscribe to.  But if you are choosing WPF vs. WinForms, you DO have a different set of interfaces that your objects must implement in order to 'participate' in the rest of the UI environment that you have chosen.
 
If you look very closely at the docs (even for 3.5) you will actually see that while (of course) all of these interfaces are in the end 'just .NET 3.5 interfaces', the ones your objects need to implement actually DO change depending on which UI platform you are targeting with them.  Again, I direct you to Rocky's latest CSLA treatise where he explores at length the (subtle) differences between the change-event-notification models in WPF, winforms, and even Silverlight.
 
Without getting of on a wild tangent here, I would just restate my opinion that the answer (in my mind) is to ensure that the right extensibility points and overridable behaviours are provided for so that anyone can intercept and wire up any specific needed eventing points as they might need to support ANY change-notification-model they my see fit to choose (which, I think, is sort of what you were advocating in the first place, no?)

HappyNomad

unread,
Nov 26, 2008, 10:07:03 AM11/26/08
to nhibernate-development
Stephen, your right that I am coming from a WPF background, but I do
not intend to ignore the needs of other GUI frameworks. I'm not aware
of the WinForms notification event model. What classes handle that?
In any case, that still doesn't change the minimum thing I am asking
to implement right now, which is to add this
template method to AbstractPersistentCollection:
protected abstract void OnCollectionChanged
( NotifyCollectionChangedAction action, object changedItem, int
index );
and then call it from all of its subclasses, whenever the collection's
contents are modified. The NotifyCollectionChangedAction enum could
even be replaced with something NH-specific if you like. With this in
place, any notification system could be easily implemented using
IUserCollectionType. And it would not be specific to
INotifyCollectionChanged or WPF in any way.


On Nov 26, 9:43 pm, "Stephen Bohlen" <sboh...@gmail.com> wrote:
> Its also true that this is actually a bit more complex that is being
> suggested here.  .NET 3.5 actually support two completely different
> 'notify-property-change' and 'notify-collection-change' eventing model --
> one for WinForms and another for WPF.  The suggestion being offered here
> seems to be solely WPF-centric and will (perhaps) meet the needs of
> WPF-adopters but won't address the needs of the winforms/webforms crowd.
>
> I (personally) think it makes more sense for the NHib core to be extensible
> and overridable rather than to explicitly support the eventing model of any
> one single UI technology.  If there are changes that need to be made to
> support this approach, then I think they make sense (to me) but to chase the
> specific implementation of any one eventing model of any one UI platform is
> a losing battle (IMHO), especially since MS has at least three *current* UI
> platforms that would have to be explicitly supported (winforms, webforms,
> and WPF).
>
> For some detail on exactly how complex (and differing) the the
> notify-changes-to-object-via-event-raising model is between these UI
> platforms, I would invite anyone to read Rocky Lhotka's most-recent book on
> his changes to CSLA to support the different platforms (although I am not a
> great big fan of CSLA per-se, reading his books on it offer some fascinating
> insight into the nuances of parts of the ,NET fx).
>
> -Steve B.
>
> On Wed, Nov 26, 2008 at 9:33 AM, Gustavo Ringel <gustavo.rin...@gmail.com>wrote:
>
> > I think the task of the persistence layer is not to be bindable to an
> > specific UI model...or to inform about something to an specific UI model.
> > So for sure it is not part of the core.
> > It may be an extension to put in the contributions...
>
> > Gustavo.
>
> >  On Wed, Nov 26, 2008 at 4:29 PM, Fabio Maulo <fabioma...@gmail.com>wrote:
>
> >>  2008/11/26 HappyNomad <happynomad...@gmail.com>
>

Stephen Bohlen

unread,
Nov 26, 2008, 10:11:36 AM11/26/08
to nhibernate-...@googlegroups.com
Example: ObservableCollection<T> is used ONLY by WPF; WinForms, MS controls for WinForms, and 3rd-party WinForms controls do not subscribe to any events raised by that class.
 
Never-the-less, I actually think that you and I are in 'violent agreement' here  that the NH core should provide a mechanism for wiring up change notification events using whatever notification methodology makes sense for your objects (I am just strongly arguing that it be in a UI-neutral manner and I think you are in agreement with that sentiment).
 
-Steve B.

324.png

HappyNomad

unread,
Nov 26, 2008, 10:15:57 AM11/26/08
to nhibernate-development
Stephen, we are definitely in agreement here. Your point about making
the solution UI-neutral is a great one. And in fact the idea I
already have in mind, to include my OnCollectionChanged() method, is
in fact UI-neutral. In my original post I just offered to take it one
step further by also implementing INotifyCollectionChanged. But if
that isn't UI-neutral then I will gladly accept refraining from taking
it that far.

Stephen Bohlen

unread,
Nov 26, 2008, 10:22:04 AM11/26/08
to nhibernate-...@googlegroups.com
HappyNomad:
 
I will take a look @ the blog post you mention in your initial post and see what we can consider doing that will support the GOAL you have of ensuring that there is a way to observe changes to collections.  The implementation may (in the end) be something different than specifically what you are proposing, but the intent of what you are after seems reasonable (to me).
 
And for the record, I have to credit Gustavo for chiming-in on UI-neutrality being a cornerstone of any implementation to address this need.
32A.png

Stephen Bohlen

unread,
Nov 26, 2008, 10:23:32 AM11/26/08
to nhibernate-...@googlegroups.com
HappyNomad:
 
Oh, and have you logged this with the NHibernate JIRA yet--? ( http://jira.nhibernate.org )

32A.png

HappyNomad

unread,
Nov 26, 2008, 11:18:52 AM11/26/08
to nhibernate-development
One modification to my original proposal. In fact, the
OnCollectionChanged method should be virtual instead of abstract, with
an empty default implementation. This is taking into consideration
that it will only be of importance when change notification is
desired. People not interested in change notification won't want to
bother with it.

Yes, please take a look at my blog post. You will see that my
PersistentObservableList<T> and PersistentObservableBag<T> classes
both contain an OnCollectionChanged method as described above
(PersistentObservableSet<T> has one that's slightly different, but it
could be refactored). The solution I created has been working fine
for NH 1.2 through 2.0. The problem is in NH 2.1, as described in my
original post, since collection methods are being explicitly
implemented. Figuring out which (non-virtual) methods to override has
already been a process of hacking. Adding my OnCollectionChanged()
method to AbstractPersistentCollection would be great since this kind
of override hacking with every new NH version would no longer be
necessary.

Well, if you want to consider different implementations, the only
significant variation I can think of is a separate OnCollectionXXX()
method for each modification type. The upside of that would be to rid
you of the NotifyCollectionChangedAction enum, which you might
consider WPF-specific. The downside is that overriding all those
methods is much more verbose than overriding just one, but acceptable
nonetheless since they would be in a dedicated subclass anyway.
Another option would be to find/make another GUI-neatral enum with
more-or-less the same values as what's in
NotifyCollectionChangedAction.

BTW, yes, I did log into JIRA just today for uploading a unit test,
although for an issue not related to the current thread. Do you want
me to create an JIRA issue regarding this request as well?


On Nov 26, 10:23 pm, Stephen Bohlen <sboh...@gmail.com> wrote:
> HappyNomad:
>
> Oh, and have you logged this with the NHibernate JIRA yet--? (http://jira.nhibernate.org)
>
> On Wed, Nov 26, 2008 at 10:22 AM, Stephen Bohlen <sboh...@gmail.com> wrote:
> > HappyNomad:
>
> > I will take a look @ the blog post you mention in your initial post and see
> > what we can consider doing that will support the GOAL you have of ensuring
> > that there is a way to observe changes to collections.  The implementation
> > may (in the end) be something different than specifically what you are
> > proposing, but the intent of what you are after seems reasonable (to me).
>
> > And for the record, I have to credit Gustavo for chiming-in
> > on UI-neutrality being a cornerstone of any implementation to address this
> > need. [?]
>  32A.png
> < 1KViewDownload

Andrew C

unread,
Dec 7, 2008, 8:22:14 PM12/7/08
to nhibernate-development
HappyNomad:

I got ObservableBag working with the new trunk by extending
PersistantGenericBag and replacing the InnerBag with an
ObservableCollection. See below:

[Serializable, DebuggerTypeProxy(typeof
(NHibernate.DebugHelpers.CollectionProxy<>))]
public class PersistentObservableBag<T> : PersistentGenericBag<T>,
INotifyCollectionChanged
{

public PersistentObservableBag(ISessionImplementor session)
: base(session)
{
}

public PersistentObservableBag(ISessionImplementor session,
ICollection<T> coll)
: base(session, coll)
{
INotifyCollectionChanged collection = coll as
INotifyCollectionChanged;
if (collection != null)
{
collection.CollectionChanged += new
NotifyCollectionChangedEventHandler(OnCollectionChanged);
}
}

public override void BeforeInitialize(ICollectionPersister
persister, int anticipatedSize)
{
this.InternalBag = (IList<T>)
persister.CollectionType.Instantiate(anticipatedSize);
INotifyCollectionChanged collection = base.InternalBag as
INotifyCollectionChanged;
if (collection != null)
{
collection.CollectionChanged += new
NotifyCollectionChangedEventHandler(OnCollectionChanged);
}
}

protected void OnCollectionChanged(object sender,
NotifyCollectionChangedEventArgs e)
{
if (CollectionChanged != null)
CollectionChanged(this, e);
}

public event NotifyCollectionChangedEventHandler
CollectionChanged;

}

public class ObservableBagType<T> : IUserCollectionType
{
#region IUserCollectionType Members

public bool Contains(object collection, object entity)
{
return ((IList<T>)collection).Contains((T)entity);
}

public IEnumerable GetElements(object collection)
{
return (IEnumerable)collection;
}

public object IndexOf(object collection, object entity)
{
return ((IList<T>)collection).IndexOf((T)entity);
}

public object ReplaceElements(object original, object target,
ICollectionPersister persister, object owner, IDictionary copyCache,
ISessionImplementor session)
{
IList<T> result = (IList<T>)target;
result.Clear();
foreach (object item in ((IEnumerable)original))
result.Add((T)item);
return result;
}

// return an instance of the inner collection type
public object Instantiate(int anticipatedSize)
{
return new ObservableCollection<T>();
}

public IPersistentCollection Instantiate(ISessionImplementor
session, ICollectionPersister persister)
{
return new PersistentObservableBag<T>(session);
}

public IPersistentCollection Wrap(ISessionImplementor session,
object collection)
{
return new PersistentObservableBag<T>(session,
(ICollection<T>)collection);
}

#endregion
}

Fabio Maulo

unread,
Dec 8, 2008, 4:55:36 AM12/8/08
to nhibernate-...@googlegroups.com
Hi Andrew.
Do you can add a wiki page, on NH-Forge (How To section), with the implementation of your Observable bag and how use it ?
You can even upload sources in your page (in nh-forge) and link the wiki to it.

For "usage" note take a look to <typedef> features (example available in NHibernate.Test.UserCollection.Parameterized)

Really thanks for your contribution and for the right spirit.
Fabio Maulo.

2008/12/7 Andrew C <awcu...@hotmail.com>



--
Fabio Maulo

Steve Wagner

unread,
Dec 8, 2008, 5:02:30 AM12/8/08
to nhibernate-...@googlegroups.com
I think this could be something useful for NHibernate Contrib.

Andrew C schrieb:

Fabio Maulo

unread,
Dec 8, 2008, 5:08:19 AM12/8/08
to nhibernate-...@googlegroups.com
2008/12/8 Steve Wagner <li...@lanwin.de>


I think this could be something useful for NHibernate Contrib.

Sure... the problem is that we don't have the project NHibernate.AppBlock.
We are adding various useful users type in uNHAddIns.
An "early" port of uNhAddIns is available in Burrow.AppBlock.
I'm working on Artorius and I don't have time to start the prj in Contrib, I'll find a "good soul" to start it.
--
Fabio Maulo

HappyNomad

unread,
Dec 8, 2008, 12:24:58 PM12/8/08
to nhibernate-development
Thanks for your help, Andrew. Subscribing to the inner collection's
change events is a great idea -- far better than the override hacking
approach I've been taking. I'm building against NH 2.0 for the time
being. Depending on further related changes made to the trunk, I'll
eventually update the solution on my blog to use the latest NH
version, including lists and sets as well.

HappyNomad

unread,
Dec 9, 2008, 12:21:38 AM12/9/08
to nhibernate-development
At the moment, the way people are figuring out how to add
observability to their NH collections for the sake of WPF, is by
downloading the solution from my blog, then looking at the demo
project. Having an instructional article to go along with the demo
would be ideal, but sorry to say I haven't written one. That would be
great if someone started one in the NH-Forge wiki, as Fabio suggests.


On Dec 8, 4:55 pm, "Fabio Maulo" <fabioma...@gmail.com> wrote:
> Hi Andrew.Do you can add a wiki page, on NH-Forge (How To section), with the
> implementation of your Observable bag and how use it ?
> You can even upload sources in your page (in nh-forge) and link the wiki to
> it.
>
> For "usage" note take a look to <typedef> features (example available
> in NHibernate.Test.UserCollection.Parameterized)
>
> Really thanks for your contribution and for the right spirit.
> Fabio Maulo.
>
> 2008/12/7 Andrew C <awcul...@hotmail.com>

HappyNomad

unread,
Dec 9, 2008, 12:43:04 AM12/9/08
to nhibernate-development
At the moment, people who are interested in using NH together with WPF
can download a working solution from my blog. I use NH with WPF on a
regular bases, but I lack permission to commit changes to NH. Hosting
the solution on my blog allows me to continuously improve upon it,
immediately make those changes available to other users. If it were
moved into NHibernate Contrib, would people like me and Andrew have
commit permissions? If not, then I think that moving it there would
be counter-productive.

Fabio Maulo

unread,
Dec 9, 2008, 6:36:43 AM12/9/08
to nhibernate-...@googlegroups.com
What do you mean with "I lack permission to commit changes to NH" ?
Which change are you talking about ?
I know various prjs using NH as DAL

2008/12/9 HappyNomad <happyn...@gmail.com>



--
Fabio Maulo

Fabio Maulo

unread,
Dec 9, 2008, 6:42:47 AM12/9/08
to nhibernate-...@googlegroups.com
Sorry... continuing the mail...

2008/12/9 Fabio Maulo <fabio...@gmail.com>

What do you mean with "I lack permission to commit changes to NH" ?
Which change are you talking about ?
I know various prjs using NH as DAL
and WPF as UI, or webForm, or MonoRail especially trough AR, or ASP.NWT MVC, or winForm.
The UI you are using have no matter with the DAL you are using so, please, maintain your changes, to work with WPF, far from NH-Core.

Thanks.
Fabio Maulo

HappyNomad

unread,
Dec 9, 2008, 12:36:20 PM12/9/08
to nhibernate-development
So then... what's this business about adding it to NHibernate Contrib?

On Dec 9, 6:42 am, "Fabio Maulo" <fabioma...@gmail.com> wrote:
> Sorry... continuing the mail...
>
> 2008/12/9 Fabio Maulo <fabioma...@gmail.com>

HappyNomad

unread,
Dec 9, 2008, 5:59:25 PM12/9/08
to nhibernate-development
I went ahead and applied Andrew's approach to my solution's persistent
observable bag, list, and set classes (the IUserCollectionType
implementations stayed the same). This is a much more elegant method
than the override hacking I was doing previously. Wish I got his
suggestion earlier! In any case, looks like additional (GUI
technology neutral) support for observability in NH-Core might not be
necessary after all, although I enjoyed our discussion. Check out my
blog entry (mentioned in the original post) to download the updated
solution.
Reply all
Reply to author
Forward
0 new messages