Метод, который выполняется в любое время при обращении к свойству класса (получить или установить)? - PullRequest
5 голосов
/ 06 декабря 2009

C # - .net 3.5

У меня есть семейство классов, которые наследуются от одного базового класса. Я хочу, чтобы метод в базовом классе вызывался каждый раз, когда к свойству в классе Derrived обращаются (получить или установить). Однако я не хочу писать код в каждое свойство для вызова базового класса ... вместо этого я надеюсь, что существует декларативный способ «погрузить» это действие в базовый класс.

Добавляя некоторые специи к требованию, мне нужно определить имя свойства, к которому был получен доступ, значение свойства и его тип.

Я полагаю, что решение было бы умной комбинацией делегата, обобщений и рефлексии. Я могу вообразить создание некоторого типа массива назначений делегатов во время выполнения, но итерации по MemberInfo в конструкторе повлияют на производительность больше, чем мне бы хотелось. Опять же, я надеюсь, что есть более прямой «декларативный» способ сделать это.

Любые идеи наиболее ценны!

Ответы [ 2 ]

4 голосов
/ 06 декабря 2009

Вы не можете сделать это автоматически, но вы можете получить 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, будет иметь такое же поведение. Presto!

2 голосов
/ 06 декабря 2009

Я не верю, что это возможно сделать декларативно, я никогда не видел, чтобы это делалось таким образом. Однако вы можете реализовать интерфейс 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...