以逻辑编程方式修改属性设置器



我需要添加属性setter的逻辑。

例如,我有一个名为"CurrentTab"的属性:

private WorkspaceViewModel _currentTab;
public WorkspaceViewModel CurrentTab
{
    get
    {
          return _currentTab;
    }
    set
    {
          _currentTab = value;
          OnPropertyChanged("CurrentTab");
    }
}

这些都很好,但我希望能够像这样定义它:

public WorkspaceViewModel CurrentTab { get; set; }

以便系统在setter运行后自动执行属性名称的OnPropertyChanged()函数,而无需添加任何特定的代码。如何确定哪些属性需要遵循这个逻辑是没有问题的,我只需要找到一种方法如何实际做到这一点。

我想让它更简单,因为我将有很多这样的属性,我想保持它的干净。

有办法吗?任何帮助都非常感激!

看一下:Fody。有一个INotifyPropertyChange插件:github

它在构建解决方案时操纵IL代码。

你只需要添加属性到视图模型:

[ImplementPropertyChanged]
public class Person 
{        
    public string GivenNames { get; set; }
    public string FamilyName { get; set; }
    public string FullName
    {
        get
        {
            return string.Format("{0} {1}", GivenNames, FamilyName);
        }
    }
}

当代码被编译时:

public class Person : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    string givenNames;
    public string GivenNames
    {
        get { return givenNames; }
        set
        {
            if (value != givenNames)
            {
                givenNames = value;
                OnPropertyChanged("GivenNames");
                OnPropertyChanged("FullName");
            }
        }
    }
    string familyName;
    public string FamilyName
    {
        get { return familyName; }
        set 
        {
            if (value != familyName)
            {
                familyName = value;
                OnPropertyChanged("FamilyName");
                OnPropertyChanged("FullName");
            }
        }
    }
    public string FullName
    {
        get
        {
            return string.Format("{0} {1}", GivenNames, FamilyName);
        }
    }
    public virtual void OnPropertyChanged(string propertyName)
    {
        var propertyChanged = PropertyChanged;
        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

这可以使用PostSharp实现,这是一种面向方面的编程方法:

在计算中,面向方面编程(AOP)是一种编程范式,旨在通过允许分离来增加模块化交叉关注。AOP构成了面向方面的基础软件开发。

你可以使用一个叫做InstanceLevelAspect:

的Aspect来实现它
/// <summary> 
/// Aspect that, when apply on a class, fully implements the interface  
/// <see cref="INotifyPropertyChanged"/> into that class, and overrides all properties to 
/// that they raise the event <see cref="INotifyPropertyChanged.PropertyChanged"/>. 
/// </summary> 
[Serializable] 
[IntroduceInterface(typeof(INotifyPropertyChanged),  
                     OverrideAction = InterfaceOverrideAction.Ignore)] 
[MulticastAttributeUsage(MulticastTargets.Class | MulticastTargets.Property,  
                          Inheritance = MulticastInheritance.Strict)] 
public sealed class NotifyPropertyChangedAttribute : InstanceLevelAspect,  
                                                     INotifyPropertyChanged 
{ 
    /// <summary> 
    /// Field bound at runtime to a delegate of the method OnPropertyChanged
    /// </summary> 
    [ImportMember("OnPropertyChanged", IsRequired = false)]
    public Action<string> OnPropertyChangedMethod; 
    /// <summary> 
    /// Method introduced in the target type (unless it is already present); 
    /// raises the <see cref="PropertyChanged"/> event. 
    /// </summary> 
    /// <param name="propertyName">Name of the property.</param> 
    [IntroduceMember(Visibility = Visibility.Family, IsVirtual = true,  
                      OverrideAction = MemberOverrideAction.Ignore)] 
    public void OnPropertyChanged(string propertyName) 
    { 
        if (this.PropertyChanged != null) 
        { 
            this.PropertyChanged(this.Instance,  
                                  new PropertyChangedEventArgs(propertyName)); 
        } 
    } 
    /// <summary> 
    /// Event introduced in the target type (unless it is already present); 
    /// raised whenever a property has changed. 
    /// </summary> 
    [IntroduceMember(OverrideAction = MemberOverrideAction.Ignore)] 
    public event PropertyChangedEventHandler PropertyChanged; 
    /// <summary> 
    /// Method intercepting any call to a property setter. 
    /// </summary> 
    /// <param name="args">Aspect arguments.</param> 
    [OnLocationSetValueAdvice,  
     MulticastPointcut( Targets = MulticastTargets.Property,  
         Attributes = MulticastAttributes.Instance)] 
    public void OnPropertySet(LocationInterceptionArgs args) 
    { 
        // Don't go further if the new value is equal to the old one. 
        // (Possibly use object.Equals here). 
        if (args.Value == args.GetCurrentValue()) 
        {
           return; 
        }
        // Actually sets the value. 
        args.ProceedSetValue(); 
        // Invoke method OnPropertyChanged (our, the base one, or the overridden one). 
        this.OnPropertyChangedMethod.Invoke(args.Location.Name); 
    } 
} 

然后,像这样在你的属性上使用它:

[NotifyPropertyChanged]
public WorkspaceViewModel CurrentTab { get; set; }

这个属性也可以应用在类级别,如果你想让你的所有属性实现NotifyPropertyChanged。关于这个例子的更多信息可以在这里找到

相关内容

  • 没有找到相关文章

最新更新