Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 以编程方式更改属性设置器逻辑_C#_.net_Reflection_Properties - Fatal编程技术网

C# 以编程方式更改属性设置器逻辑

C# 以编程方式更改属性设置器逻辑,c#,.net,reflection,properties,C#,.net,Reflection,Properties,我需要添加属性设置程序的逻辑 例如,我有一个名为“CurrentTab”的属性: 这一切都很好,也很有效,但我希望能够这样定义: public WorkspaceViewModel CurrentTab { get; set; } [NotifyPropertyChanged] public WorkspaceViewModel CurrentTab { get; set; } 因此,在setter运行后,系统会自动为属性名执行OnPropertyChanged()函数,而无需我添加任何特定

我需要添加属性设置程序的逻辑

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

这一切都很好,也很有效,但我希望能够这样定义:

public WorkspaceViewModel CurrentTab { get; set; }
[NotifyPropertyChanged]
public WorkspaceViewModel CurrentTab { get; set; }
因此,在setter运行后,系统会自动为属性名执行OnPropertyChanged()函数,而无需我添加任何特定代码。 如何确定哪些属性需要遵循这个逻辑是没有问题的,我只需要找到一种方法来真正做到这一点

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

有办法吗? 非常感谢您的帮助

看一看:。有一个用于INotifyPropertyChange的外接程序:

它是在构建解决方案时操作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));
        }
    }
}

这可以通过以下方法实现:

在计算中,面向方面编程(AOP)是一种编程方法 通过允许分离来增加模块化的范例 跨领域关注的问题。AOP是面向方面的基础 软件开发

您可以使用名为
InstanceLevelAspect
的方面来实现这一点:

/// <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
,则此属性也可以应用于类级别。关于这个例子的更多信息可以找到

PostSharp看起来很有希望,但我最终使用了pwas的Fody答案。主要是因为PostSharp不是免费的。谢谢你的意见!
[NotifyPropertyChanged]
public WorkspaceViewModel CurrentTab { get; set; }