每次访问(获取或设置)类属性时执行的方法?

Posted

技术标签:

【中文标题】每次访问(获取或设置)类属性时执行的方法?【英文标题】:A method that executes any time a class property is accessed (get or set)? 【发布时间】:2010-12-23 15:33:36 【问题描述】:

C# - .net 3.5

我有一系列继承自同一个基类的类。 我希望在派生类中的属性被访问(获取或设置)时调用基类中的方法。但是,我不想在每个属性中编写代码来调用基类......相反,我希望有一种声明方式可以将此活动“吸收”到基类中。

为需求添加一些调料,我确实需要确定被访问的属性的名称、属性值及其类型。

我认为解决方案是委托、泛型和反射的巧妙组合。我可以设想在运行时创建某种类型的委托分配数组,但是在构造函数中迭代 MemberInfo 会比我想要的更影响性能。同样,我希望有一种更直接的“声明式”方式来做到这一点。

任何想法都非常感谢!

【问题讨论】:

【参考方案1】:

您无法自动完成,但您几乎可以免费获得 95%。这是面向方面编程的经典案例。查看PostSharp,它有OnFieldAccessAspect 类。以下是解决问题的方法:

[Serializable]
public class FieldLogger : OnFieldAccessAspect 
    public override void OnGetValue(FieldAccessEventArgs eventArgs) 
        Console.WriteLine(eventArgs.InstanceTag);
        Console.WriteLine("got value!");
        base.OnGetValue(eventArgs);
    

    public override void OnSetValue(FieldAccessEventArgs eventArgs) 
        int i = (int?)eventArgs.InstanceTag ?? 0;
        eventArgs.InstanceTag = i + 1;
        Console.WriteLine("value set!");
        base.OnSetValue(eventArgs);
    

    public override InstanceTagRequest GetInstanceTagRequest() 
        return new InstanceTagRequest("logger", new Guid("4f8a4963-82bf-4d32-8775-42cc3cd119bd"), false);
    

现在,从 FieldLogger 继承的任何东西都将获得相同的行为。快!

【讨论】:

【参考方案2】:

我不相信这是可能的,我从来没有见过它这样做。您可以做的是在基类上实现 INotifyPropertyChanged 接口,并在基类中实现接口。像这样的:

public class A : INotifyPropertyChanged


    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion

    protected virtual void RaiseOnPropertyChanged(object sender, string propertyName)
    
        if (this.PropertyChanged != null)
            PropertyChanged(sender, new PropertyChangedEventArgs(propertyName);
    

    public A()
    
        this.PropertyChanged += new PropertyChangedEventHandler(A_PropertyChanged);
    

    void A_PropertyChanged(object sender, PropertyChangedEventArgs e)
    
        //centralised code here that deals with the changed property
    



public class B : A

    public string MyProperty
    
        get  return _myProperty; 
        set 
        
            _myProperty = value;
            RaiseOnPropertyChanged(this, "MyProperty");
        
    

    public string _myProperty = null;

【讨论】:

我还应该指出,虽然 INotifyPropertyChanged 允许您传递属性名称,但不需要火箭科学家将概念更进一步并编写您自己的接口版本,该接口也允许要传递的属性值等。尽管您提出的建议虽然在理论上听起来很聪明,但会给您的应用程序增加很多开销,并且您必须考虑在代码中使用条件编译开关。

以上是关于每次访问(获取或设置)类属性时执行的方法?的主要内容,如果未能解决你的问题,请参考以下文章

php常用的魔术方法

C#中基类属性值在子类中设置,如何在基类的方法中获取子类设置的值?

反射常见方法

在 Gradle 中,如何在每次执行 JUnit 测试类之前设置唯一的系统属性?

.NET 中属性的嵌套类访问方法

设置类的任何属性时,有没有办法调用方法?