在任何时候访问类属性(获取或设置)时执行的方法?

时间:2009-12-05 22:45:48

标签: c# generics reflection .net-3.5 delegates

C# - .net 3.5

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

在需求中添加一些spice,我需要确定访问的属性的名称,属性值及其类型。

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

非常感谢任何想法!

2 个答案:

答案 0 :(得分:4)

你不能自动完成,但你可以免费获得95%。这是面向方面编程的经典案例。查看PostSharpOnFieldAccessAspect。以下是您可以解决问题的方法:

[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继承的任何内容都会获得相同的行为。的Presto!

答案 1 :(得分: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;
}