I have the following scenario:
Code:
class A: INotifyPropertyChanged
{
long id;
string name;
public virtual string Id
{
get { return id; }
set { id = value; }
}
public virtual string Name
{
get { return name; }
set
{
name = value;
FirePropertyChangedEvent("Name");
}
}
public virtual event NotifyPropertyChanged PropertyChanged;
...
}
class B
{
object valueObject;
public virtual object ValueObject // <<< mapped as "any", lazy
{
get { return this.valueObject; }
set { this.valueObject = value; }
}
}
Now object of my B class is hibernated and A is mapped there as
lazy so proxy is created at the beginning when B is loaded. As result the following test fails:
Code:
[Test]
public void SubscibeToEventsOfLazyLoadedObject()
{
// == instantiate objects, subscribe to property changes and check if events work
B b = new B();
A a = new A();
b.ValueObject = a;
int changesCount = 0;
INotifyPropertyChanged notifiable = (INotifyPropertyChanged)b.ValueObject;
notifiable.PropertyChanged += delegate { changesCount++; };
a.Name = "name1";
Assert.AreEqual(1, changesCount);
// == save B object into repository
Repository repository1 = new Repository();
repository1.Create("SubscibeToEventsOfLazyLoadedObject.db");
repository1.Save(b);
repository1.Close();
// == open database, load B and re-subscribe to it after it is loaded
Repository repository2 = new Repository();
repository2.Open("SubscibeToEventsOfLazyLoadedObject.db");
B b2 = repository2.Load<B>();
INotifyPropertyChanged notifiable = (INotifyPropertyChanged)b.ValueObject;
notifiable.PropertyChanged += delegate { changesCount++; };
A a2 = (A)b.ValueObject;
a2.Name = "name2"; // fires PropertyChanged event
Assert.AreEqual(2, changesCount); // BANG! no changes
}
Is it a feature or a bug?
I'd expect that proxy object get's replaced by a real object once I access PropertyChanged in it? And that my event subscribers are still ok. But it's not. My unit test subscribes to AProxy43214.PropertyChanged nicely and when I'm accessing
a2.Name - another instance of A get's created which NHibernate uses to load all properties and then it is also used to set Name property, but that instance does not have my PropertyChanged event initialized anymore and event is not fired :(.