Is there a way to call a method when any class property is set?

So, what I'm trying to do is call one propertyWasSet () function when some property is set in the C # class (back, the WasGot () property when it is received). I would also like to know which get property was called.

I would like to support the dictator of the properties that are “set”, and check the “get” action if they are still set (and throw an error if it was not).

I am looking at msdn documentation for reflection, delegates, etc., but I'm not quite sure if this is possible.

Is there any way to do this? or to trigger an event when one of these functions is called, which can be intercepted in the base class or something like that?

+6
reflection c # properties delegates
source share
5 answers

I wrote an interceptor next week for Set, which can be easily expanded for Get, it uses RealProxy, which means that your base class should output MarshalByRefObject.

Another fancy option is to have an abstract class and use Reflection Emit to create a specific class that completes all the properties.

You can also look at code generators to get around this or PostSharp ...

The performance for this solution is not stellar, but for greater UI binding, it should be fast enough. It can be improved by creating LCG methods for calling proxies.

public interface IInterceptorNotifiable { void OnPropertyChanged(string propertyName); } /// <summary> /// A simple RealProxy based property interceptor /// Will call OnPropertyChanged whenever and property on the child object is changed /// </summary> public class Interceptor<T> where T : MarshalByRefObject, IInterceptorNotifiable, new() { class InterceptorProxy : RealProxy { T proxy; T target; EventHandler<PropertyChangedEventArgs> OnPropertyChanged; public InterceptorProxy(T target) : base(typeof(T)) { this.target = target; } public override object GetTransparentProxy() { proxy = (T)base.GetTransparentProxy(); return proxy; } public override IMessage Invoke(IMessage msg) { IMethodCallMessage call = msg as IMethodCallMessage; if (call != null) { var result = InvokeMethod(call); if (call.MethodName.StartsWith("set_")) { string propName = call.MethodName.Substring(4); target.OnPropertyChanged(propName); } return result; } else { throw new NotSupportedException(); } } IMethodReturnMessage InvokeMethod(IMethodCallMessage callMsg) { return RemotingServices.ExecuteMessage(target, callMsg); } } public static T Create() { var interceptor = new InterceptorProxy(new T()); return (T)interceptor.GetTransparentProxy(); } private Interceptor() { } } 

Using:

  class Foo : MarshalByRefObject, IInterceptorNotifiable { public int PublicProp { get; set; } public string lastPropertyChanged; public void OnPropertyChanged(string propertyName) { lastPropertyChanged = propertyName; } } [Test] public void TestPropertyInterception() { var foo = Interceptor<Foo>.Create(); foo.PublicProp = 100; Assert.AreEqual("PublicProp", foo.lastPropertyChanged); } } 
+7
source share

You might want to learn PostSharp for this kind of task. It is designed to work on top of C # (or any .NET language, for that matter), and has the advantage of not cluttering your code with reflection in addition. In fact, I don't believe that you could find a solution that purely uses C # / Reflection without manually adding code for each of your properties, so I definitely recommend PostSharp as a way out.

+3
source share

I think you need a very similar WPF dependency system. Perhaps you should take a look at its implementation. Anyway, you can add the capture code to the getter and setter of each property too.

0
source share

There is nothing like it unless you create it yourself.

0
source share

The SET part of your query is very similar to the WPF dependency property system. But the GET part is so unusual that it is missing even in the WPF dependency system!

0
source share

All Articles