我正在使用PostSharp的NotifyPropertyChanged方面。
我有一种情况,我需要触发
PropertyChanged
因为我的用例似乎太复杂了,PostSharp很难弄清楚。以下是我的视图模型的相关摘录:
private RelayCommand _authenticateCommand;
[IgnoreAutoChangeNotificationAttribute]
public ICommand AuthenticateCommand
{
get { return _authenticateCommand ?? (_authenticateCommand = new RelayCommand(Authenticate, _ => IsNotAuthenticated)); }
}
private void Authenticate(object obj)
{
var result = _dialogService.OpenAuthenticationDialog();
if (result.HasValue && result.Value)
{
_mainViewModel.Update();
}
// At this point I need to trigger NotifyPropertyChanged for IsNotAuthenticated,
// because the authentication dialog causes changes
// to the _authenticationViewModel's IsLoggedIn property.
}
public bool IsNotAuthenticated
{
get
{
return !_authenticationViewModel.IsLoggedIn;
}
}
正如我在上面代码中的注释中所描述的,当身份验证对话框完成时,我需要触发
NotifyPropertyChanged
的事件
IsNotAuthenticated
,因为对话框很可能更改了值。
阅读
the documentation
,看起来应该很容易:
目标类可以通过实现NotifyPropertyChangedAttributeTargetClass类中记录的一个或多个成员来自定义NotifyPPropertyChangedAttribute方面。
从
NotifyPropertyChangedAttributeTargetClass.OnPropertyChanged
第页:
引发PropertyChanged事件。如果目标代码中已经存在此方法,NotifyPropertyChangedAttribute方面将使用它来引发PropertyChanged事件。否则,方面将把方法引入目标类。
太好了,所以我尝试实现一个空
OnPropertyChanged
方法,以为它会被PostSharp的版本取代,但唉,它反而打破了所有的通知逻辑。这是我替换之前生成的代码的样子
OnPropertyChanged
:
protected void OnPropertyChanged(string propertyName)
{
this.<>z__aspect0.OnPropertyChanged(propertyName);
}
这就是它的样子:
protected void OnPropertyChanged(string propertyName)
{
this.<>z__aspect0.OnMethodEntry(null);
try
{
}
finally
{
this.<>z__aspect0.OnMethodExit(null);
}
}
测试代码时,它在第一种情况下工作,而不是在第二种情况下。所以我实现了一个空
OnPropertyChanged
导致功能停止工作。
我猜文件是在撒谎?它明确表示(强调我的)
如果此方法为
已存在
在目标代码中,NotifyPropertyChangedAttribute方面
将使用它
引发PropertyChanged事件。”——但上面生成的代码和我的测试表明并非如此。
在我弄清楚我是谁或PostSharp做错了什么之前,我最终所做的是“同时”创建自己的方面,如下所示:
[Serializable]
class PropertyChangedTriggerAttribute : MethodInterceptionAspect
{
public override void OnInvoke(MethodInterceptionArgs args)
{
var inpc = args.Method.DeclaringType;
if (inpc == null) throw new InvalidOperationException("PropertyChangedTriggerAttribute used on an object that doesn't have an OnPropertyChanged(System.String) method.");
var opc = inpc.GetMethod("OnPropertyChanged", BindingFlags.Instance | BindingFlags.NonPublic);
var value = (string) args.Arguments.GetArgument(0);
opc.Invoke(args.Instance, new object[] { value });
}
}
然后用它标记类中的一个方法:
[PropertyChangedTrigger]
private void TriggerOnPropertyChanged(string propertyName)
{
}
现在我可以称之为,它反过来触发
OnPropertyChanged
为了我。
你知道我做错了什么吗?有人用这个为他们工作吗?