Created
April 7, 2011 02:30
-
-
Save caleb-vear/906916 to your computer and use it in GitHub Desktop.
Sample code for a blog post I wrote about: WPF Bindings Not Updating When PropertyChanged Raised When Bound Against a Proxy Object
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" > | |
<session-factory name="YourAppName"> | |
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property> | |
<property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property> | |
<property name="connection.connection_string"> | |
Server=(local);initial catalog=nhibernate;Integrated Security=SSPI | |
</property> | |
<property name="proxyfactory.factory_class"> YouProjectNameSpace.FixDataBindingProxyFactoryFactory, YourProjectAssembly</property> | |
</session-factory> | |
</hibernate-configuration> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ShoppingCart : INotifyPropertyChanged | |
{ | |
public virtual Guid Id { get; private set; } | |
public virtual IList<CartItem> _items = new ObservableCollection<CartItem>(); | |
public virtual IEnumerable<CartItem> { get { return _items; } } | |
public virtual decimal Total { get { return _items.Sum(i => i.Price); } } | |
public virtual void AddItem(CartItem item) | |
{ | |
_items.Add(item); | |
// We raise this event to notify subscribers that our Total has very likely changed its value. | |
PropertyChanged(this, new PropertyChangedEventArgs("Total")); | |
} | |
public virtual event PropertyChangedEventHandler PropertyChanged = delegate {}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class FixDataBindingLazyInitializer : LazyInitializer | |
{ | |
private PropertyChangedEventHandler _subscribers = delegate { }; | |
public object ProxyInstance { get; set; } | |
public FixDataBindingInterceptor(String entityName, Type persistentClass, object id, MethodInfo getIdentifierMethod, MethodInfo setIdentifierMethod, IAbstractComponentType aType, ISessionImplementor session) | |
: base(entityName, persistentClass, id, getIdentifierMethod, setIdentifierMethod, aType, session) | |
{ | |
} | |
public override void Intercept(Castle.DynamicProxy.IInvocation invocation) | |
{ | |
// WPF will call a method named add_PropertyChanged to subscribe itself to the property changed events of | |
// the given entity. The method to call is stored in invocation.Arguments[0]. We get this and add it to the | |
// proxy subscriber list. | |
if (invocation.Method.Name.EndsWith("PropertyChanged")) | |
{ | |
PropertyChangedEventHandler propertyChangedEventHandler = (PropertyChangedEventHandler)invocation.Arguments[0]; | |
if (invocation.Method.Name.StartsWith("add_")) | |
{ | |
_subscribers += propertyChangedEventHandler; | |
} | |
else | |
{ | |
_subscribers -= propertyChangedEventHandler; | |
} | |
} | |
else | |
{ | |
base.Intercept(invocation); | |
} | |
} | |
public override void Initialize() | |
{ | |
base.Initialize(); | |
var notifyPropertyChanged = Target as INotifyPropertyChanged; | |
if (notifyPropertyChanged != null) | |
{ | |
// We subscribe to our Target's property changed event so we can pass it on | |
// to any objects that subscribe to the proxies event. | |
notifyPropertyChanged.PropertyChanged += TargetPropertyChanged; | |
} | |
} | |
void TargetPropertyChanged(object sender, PropertyChangedEventArgs e) | |
{ | |
_subscribers(ProxyInstance, e); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class FixDataBindingProxyFactory : ProxyFactory | |
{ | |
public override INHibernateProxy GetProxy(object id, ISessionImplementor session) | |
{ | |
// If it is not a proxy for a class do what you usually did. | |
if (!IsClassProxy) return base.GetProxy(id, session); | |
try | |
{ | |
var initializer = new FixDataBindingLazyInitializer(EntityName, PersistentClass, id, | |
GetIdentifierMethod, SetIdentifierMethod, ComponentIdType, session); | |
// Add to the list of the interfaces that the proxy class will support the INotifyPropertyChanged interface. | |
// This is only needed in the case when we need to cast our proxy object as INotifyPropertyChanged interface. | |
var extraInterfaces = new[] {typeof (INotifyPropertyChanged)}; | |
var interfaces = Interfaces.Concat(extraInterfaces).ToArray(); | |
object generatedProxy = DefaultProxyGenerator.CreateClassProxy(PersistentClass, interfaces, initializer); | |
initializer._constructed = true; | |
initializer.ProxyInstance = generatedProxy; | |
return (INHibernateProxy)generatedProxy; | |
} | |
catch (Exception e) | |
{ | |
log.Error("Creating a proxy instance failed", e); | |
throw new HibernateException("Creating a proxy instance failed", e); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class FixDataBindingProxyFactoryFactory : IProxyFactoryFactory | |
{ | |
public IProxyFactory BuildProxyFactory() | |
{ | |
return new FixDataBindingProxyFactory(); | |
} | |
public bool IsInstrumented(Type entityClass) | |
{ | |
return true; | |
} | |
public IProxyValidator ProxyValidator | |
{ | |
get { return new DynProxyTypeValidator(); } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Can you please update the code to use the new build in proxy in NH >= 3.3