Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A method that executes any time a class property is accessed (get or set)?

C# - .net 3.5

I have a family of classes that inherit from the same base class. I want a method in the base class to be invoked any time a property in a derrived class is accessed (get or set). However, I don't want to write code in each and every property to call the base class... instead, I am hoping there is a declarative way to "sink" this activity into the base class.

Adding some spice to the requirement, I do need to determine the name of the property that was accessed, the property value and its type.

I imagine the solution would be a clever combination of a delegate, generics, and reflection. I can envision creating some type of array of delegate assignments at runtime, but iterating over the MemberInfo in the constructor would impact performance more than I'd like. Again, I'm hoping there is a more direct "declarative" way to do this.

Any ideas are most appreciated!

like image 599
Jeff Avatar asked Dec 05 '09 22:12

Jeff


People also ask

What is the use of Get and set in C#?

A get property accessor is used to return the property value, and a set property accessor is used to assign a new value. In C# 9 and later, an init property accessor is used to assign a new value only during object construction. These accessors can have different access levels.

When a method or property can be accessed from outside the class?

Internal and external interface. In object-oriented programming, properties and methods are split into two groups: Internal interface – methods and properties, accessible from other methods of the class, but not from the outside. External interface – methods and properties, accessible also from outside the class.

What method is automatically executed whenever a new instance of the class which the method belongs to has been instantiated?

Every class should have a method with the special name __init__. This initializer method is automatically called whenever a new instance of Point is created.

How do we access properties and method of a class?

Once you have an object, you can use the -> notation to access methods and properties of the object: $object -> propertyname $object -> methodname ([ arg, ... ] )


2 Answers

You can't do it automatically, but you can pretty much get 95% for free. This is a classic case for aspect-oriented programming. Check out PostSharp, which has the OnFieldAccessAspect class. Here's how you might solve your problem:

[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);
    }
}

Now, anything that inherits from FieldLogger will get the same behavior. Presto!

like image 152
John Feminella Avatar answered Sep 23 '22 23:09

John Feminella


I don't believe this is possible to do declaratively, i have never seen it done that way. What you can do though is implement the INotifyPropertyChanged interface on your base class, and have the implementation of the interface in the base class. Something like this:

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;
}
like image 37
slugster Avatar answered Sep 23 '22 23:09

slugster