-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 14 posts ] 
Author Message
 Post subject: NHibernate 2.0 flags PropertyChanged event as not virtual?
PostPosted: Mon Sep 01, 2008 8:04 am 
Newbie

Joined: Mon Sep 01, 2008 6:31 am
Posts: 11
Location: Zwolle, The Netherlands
Upgraded my VB 2005 project today from NH 1.2 to 2.0 and read the note that with it comes "Stricter checks for proxying classes (all public methods must be virtual)"

However the session factory init starts throwing the following errors for every single businessobject class in my project.
- method add_PropertyChanged should be virtual
- method remove_PropertyChanged should be virtual

but they are just referring to a public IPropertyChanged event and I cannot set the event to be overridable in VB (can you in C#?) The referred methods do not seem to exist explicitly in my classes and it used to work under NH 1.2 with lazy loading. All my businessobject classes derive from a base class that implements INotifyPropertyChanged.

Help would be appreciated
Theo

_________________
Theo
Nairobi, Kenya


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 01, 2008 8:35 am 
Newbie

Joined: Mon Oct 09, 2006 2:50 pm
Posts: 15
hi,

in c# you can set your events as virtual:

Code:
public virtual event PropertyChangedEventHandler PropertyChanged;


another way is to implement the event in your baseclass as following:

Code:
        [NonSerialized]
        protected PropertyChangedEventHandler _nonSerializableHandlersForPropertyChanged;

        protected PropertyChangedEventHandler _serializableHandlersForPropertyChanged;

        public virtual event PropertyChangedEventHandler PropertyChanged
        {
            add
            {
                if (value != null)
                    if (value.Method.IsPublic &&
                        (value.Method.DeclaringType.IsSerializable ||
                         value.Method.IsStatic))
                        _serializableHandlersForPropertyChanged = (PropertyChangedEventHandler)Delegate.Combine(_serializableHandlersForPropertyChanged, value);
                    else
                        _nonSerializableHandlersForPropertyChanged = (PropertyChangedEventHandler)Delegate.Combine(_nonSerializableHandlersForPropertyChanged, value);
            }
            remove
            {
                if (value != null)
                    if (value.Method.IsPublic &&
                        (value.Method.DeclaringType.IsSerializable ||
                         value.Method.IsStatic))
                        _serializableHandlersForPropertyChanged = (PropertyChangedEventHandler)Delegate.Remove(_serializableHandlersForPropertyChanged, value);
                    else
                        _nonSerializableHandlersForPropertyChanged = (PropertyChangedEventHandler)Delegate.Remove(_nonSerializableHandlersForPropertyChanged, value);
            }
        }


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 01, 2008 8:35 am 
Newbie

Joined: Mon Oct 09, 2006 2:50 pm
Posts: 15
// edit: sorry, was double posting.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 01, 2008 12:44 pm 
Newbie

Joined: Mon Sep 01, 2008 6:31 am
Posts: 11
Location: Zwolle, The Netherlands
Thanks for the clarification, that virtual properties are possible with C#. I cannot say that I (yet) fully understand what you are trying to achieve/illustrate with your example though ;-)

But does this mean that NHibernate 2.0 only works in C# or would there be a sensible workaround for VB 2005? As said before the sourcecode worked under the previous NHibernate version lazy loading and all. This seems like a big no-go for my project this way.

_________________
Theo
Nairobi, Kenya


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 11, 2008 4:17 pm 
Regular
Regular

Joined: Tue Oct 16, 2007 9:45 am
Posts: 93
I think what he is trying to tell you is that you have to mark this "event" as virtual. I had the same problem. Probably has to do something with proxy classes creation. I think in VB it might be "Overridable" that you are looking for.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 12, 2008 2:07 am 
Newbie

Joined: Mon Sep 01, 2008 6:31 am
Posts: 11
Location: Zwolle, The Netherlands
Unfortunately virtual / overridable events are not part of the VB language definition of .NET 2.0 (and also not in .NET 3.0). The error definitly has to do with the creation of proxy classes.

Effectively this would prevent any VB developer to map VB classes that implement for example INotifyPropertyChanged as lazy. This would render NHibernate useless for the VB developer as far as I can see now since this NPC event is a core event in data binding.

_________________
Theo
Nairobi, Kenya


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 12, 2008 8:28 am 
Regular
Regular

Joined: Tue Oct 16, 2007 9:45 am
Posts: 93
I noticed the problem when I downloaded 2.0 and recompiled, but since my project is in C# did not think much about it. Maybe you can log this as possible bug.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 26, 2008 10:18 am 
Newbie

Joined: Fri Sep 26, 2008 10:09 am
Posts: 2
Theo, did you find a solution to this problem?

I just ran across the same issue. I searched to see if this had come up on the nhibernate mailing list but I didn't see it. JIRA appears to not be functional so I couldn't tell if a bug had been entered. I plan on rolling back to NHibernate 1.2 for now (this seems easier than convincing management to allow the developers to use C# instead.)


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 04, 2009 4:46 am 
Newbie

Joined: Mon Sep 01, 2008 6:31 am
Posts: 11
Location: Zwolle, The Netherlands
No did not yet find any solution for this NHibernate 2.0 problem with VB events. Have waited for the next release to see if it would be addressed there. Unfortunately have just tried to run under 2.0.1GA and the same problem persists.

VB2005 does not support Overridable (=virtual in C#) on event declarations (not even when implementing them as custtom events like below)....

<NonSerialized()> _
Dim m_PropertyChangedHandler As PropertyChangedEventHandler
Public Custom Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
AddHandler(ByVal value As PropertyChangedEventHandler)
m_PropertyChangedHandler = DirectCast([Delegate].Combine(m_PropertyChangedHandler, value), PropertyChangedEventHandler)
End AddHandler

RemoveHandler(ByVal value As PropertyChangedEventHandler)
m_PropertyChangedHandler = DirectCast([Delegate].Remove(m_PropertyChangedHandler, value), PropertyChangedEventHandler)
End RemoveHandler

RaiseEvent(ByVal sender As Object, ByVal e As PropertyChangedEventArgs)
If m_PropertyChangedHandler IsNot Nothing Then
m_PropertyChangedHandler(sender, e)
End If
End RaiseEvent
End Event

Friend Overridable Sub NotifyPropertyChanged(ByVal Information As String, Optional ByVal sender As Object = Nothing)
If sender Is Nothing Then
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(Information))
Else
RaiseEvent PropertyChanged(sender, New PropertyChangedEventArgs(Information))
End If
End Sub

Since databinding in .NET2.0 relies extensively on this interface I am forced to forget about lazy loading or about databinding. Neither of them are an option really (just as moving to C# isn't) So basically NHibernate 2.0 is NOT VB compatible it seems. Or would anyone out there know a way how to tell NHibernate to ignore event declarations in it's checking?

Do you know where I can post this to the NHibernate developers as a bug?

_________________
Theo
Nairobi, Kenya


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 04, 2009 5:29 am 
Contributor
Contributor

Joined: Thu May 12, 2005 9:45 am
Posts: 593
Location: nhibernate.org
IIRC, there is a way to turn off this checking. Try setting use_proxy_validator to false.

_________________
Pierre Henri Kuaté.
Get NHibernate in Action Now!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 04, 2009 8:16 am 
Newbie

Joined: Mon Sep 01, 2008 6:31 am
Posts: 11
Location: Zwolle, The Netherlands
Thanks, that indeed prevents the error!
Though it will probably increase the danger of having classes that are not fully up to standard for lazy loading... At least now I can choose when I want to fix those errors :-)

Ta,
Theo

_________________
Theo
Nairobi, Kenya


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 04, 2009 8:17 am 
Newbie

Joined: Fri Sep 26, 2008 10:09 am
Posts: 2
I recently posted this question on the NHUsers group. I think the question might be stuck in moderation though because it appears on the google groups website but I never saw it on the actual mailing list.

I built a fresh copy of NHibernate based on the trunk code and can confirm the issue still exists.

I think setting use_proxy_validator to false as KPixel suggests would work, but you'd also lose validation on your properties and methods.

Ayende implemented static proxies using Post Sharp. He says this removes the need to declare methods virtual which would fix our issue. Currently his Post Sharp work is in a branch that looks like it hasn't really been touched since he created it in October. I haven't built NHibernate using that branch yet but if I do I'll post back here and let you know how it went.


Top
 Profile  
 
 Post subject: Worse news about NHibernate proxies
PostPosted: Fri Mar 13, 2009 8:24 am 
Newbie

Joined: Mon Sep 01, 2008 6:31 am
Posts: 11
Location: Zwolle, The Netherlands
Only after some time did I find out that the proxy validator is right and I am wrong in my assumption that the proxy and my lazy loaded business object are one and the same thing. Apparently they are NOT the same instance. They both derive from the Booking class, but are not the same instance. This might seem as not so much of a problem as long as you only use one or the other (which the session manages for us).

HOWEVER, when it comes to public events defined in my Booking class then it does matter! Since the proxy class derives from Booking it also implements INotifyPropertyChanged. So I can define a variable referring to this object as "Private WithEvents b as Booking". However when b is a Booking-proxy rather than my normal class then I will NEVER receive any PC events! This because the proxy will just forward the calls to properties to the "invisible" Booking instance but will not pass event subscriptions on to this object. So when calling b.Comments = "Hi There" then the PC event does fire from the (inner/invisible) Booking object but not from the proxy!!!

This is very hard to spot since both instances say that they are a Booking and that they have the same BookingID. And with VB you cannot define Custom Events as Virtual/Overridable (not in VB2005 and also not in VB2008) so the proxy has no way of forwarding the subscription to the underlying/actual instance .... why the proxie is defined as a separate instance from the underlying booking is a mystery to me.

_________________
Theo
Nairobi, Kenya


Top
 Profile  
 
 Post subject: Found a workaround!
PostPosted: Tue Mar 17, 2009 7:26 am 
Newbie

Joined: Mon Sep 01, 2008 6:31 am
Posts: 11
Location: Zwolle, The Netherlands
Since VB cannot define an event as virtual and this would prevent the use of INotifyPropertyChanged i.c.w. Lazy loading this is the workaround. Add a C# project to the VB solution in which you define an abstract base class that implents the virtual event. Then let the VB classes inherit from that class. It is not good OO practice but it works ;-)

So for example in C# dll

Code:
using System;
using System.ComponentModel;
namespace MAF.DB.Foundation
{
    public abstract class NotifyPropertyChangedFoundation : INotifyPropertyChanged
    {
        public virtual event PropertyChangedEventHandler PropertyChanged;

        public virtual void NotifyPropertyChanged(String Information)
        {
            if (PropertyChanged != null)
            {
                NotifyPropertyChanged(Information, this);
            }
        }

        public virtual void NotifyPropertyChanged(String Information, object sender)
        {
            if (PropertyChanged != null)
            {
                if (sender == null) { sender = this; }
                PropertyChanged(sender, new PropertyChangedEventArgs(Information));
            }
        }
    }
}


And then in VB

Code:
Namespace MAF.DB.BusinessObject
   Public MustInherit Class BusinessObjectBase
      Inherits DB.Foundation.NotifyPropertyChangedFoundation 'Implements INotifyPropertyChanged

... etc

   End Class

_________________
Theo
Nairobi, Kenya


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 14 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.