问题
I currently have a setter method which looks like this:
private string _a;
public virtual string A
{
get { return _a; }
set
{
if (_a!= value)
{
if (this.OnPropertyChanging("A", _a, value))
{
var previousValue = _a;
_a = value;
this.OnPropertyChanged("A", previousValue, value);
}
}
}
}
I have implemented this with help from Dr Wily's Apprentice (http://stackoverflow.com/a/8578507/981225), with a custom Changing handler that keeps track of the old and current value, as well as the ability to set the Changing event as 'Cancelled', such that the PropertyChange will not occur.
This works perfectly. However, we have hundreds of properties and this is a lot of code the duplicate.
I have used Castle's DynamicProxy in the past, to avoid having to write 'OnPropertyChanged("A")'.
How can I implement the logic within this setter, as part of the Proxy's Intercept method? Is it possible? Thank you.
回答1:
Maybe I'm a bit late, but I came across a similar task in the Linq-To-SharePoint model. I sketched some code if some one's still wondering.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Castle.DynamicProxy;
using System.Reflection;
using System.ComponentModel;
namespace DemoSpace
{
public abstract class EntityBase : INotifyPropertyChanged, INotifyPropertyChanging
{
public virtual void OnPropertyChanging(string propertyName, object value)
{
if ((null != PropertyChanging))
{
PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
}
}
public virtual void OnPropertyChanged(string propertyName)
{
if ((null != PropertyChanged))
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public event PropertyChangingEventHandler PropertyChanging;
}
public class DemoInterceptor<T> : IInterceptor where T : EntityBase
{
private T _target;
public DemoInterceptor(T target)
{
_target = target;
}
public void Intercept(IInvocation invocation)
{
if (invocation.Method.IsPublic && invocation.Method.Name.StartsWith("set_"))
{
string propertyName = invocation.Method.Name.Substring(4);
string privateFieldName = ResolvePropName(propertyName);
object original_value =
typeof(T).GetField(privateFieldName, BindingFlags.NonPublic | BindingFlags.Instance).GetValue(_target);
_target.OnPropertyChanging(propertyName, original_value);
invocation.Method.Invoke(_target, invocation.Arguments);
_target.OnPropertyChanged(propertyName);
}
else
{
invocation.ReturnValue = invocation.Method.Invoke(_target, invocation.Arguments);
}
}
public virtual string ResolvePropName(string propertyName)
{
return "_" + propertyName.Substring(0, 1).ToLower() + propertyName.Substring(1);
}
}
}
来源:https://stackoverflow.com/questions/8580307/handling-propertychanging-propertychanged-via-castles-dynamicproxy