我目前有一个setter方法,如下所示:
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);
}
}
}
}
我已经在Wily博士的Apprentice(http://stackoverflow.com/a/8578507/981225)的帮助下实现了这一功能,其中包含一个自定义的更改处理程序,可以跟踪旧的和当前的值,以及将Changing事件设置为'Canceled',这样就不会发生PropertyChange。
这完美无缺。但是,我们有数百个属性,这是重复的很多代码。
我过去使用过Castle的DynamicProxy,以避免写'OnPropertyChanged(“A”)'。
如何在此setter中实现逻辑,作为Proxy的Intercept方法的一部分?可能吗?谢谢。
答案 0 :(得分:1)
也许我有点迟了,但我在Linq-To-SharePoint模型中遇到了类似的任务。如果有人还在想,我会勾勒出一些代码。
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);
}
}
}