1

well ive read a lot of posts here and there about why it isnt reliable to raise events via reflection.. my problem is this.. im using PostSharp to define an interface which allows a class to notify before and after a property is changed..

the NotifyAttribute ive created needs to be able to raise the PropertyBeforeChange and PropertAfterChange events.. thing is, even though i can retrieve the event, its GetRaiseMethod() returns null and hence i cannot raise the said events.. how can i go about doing that?

using PostSharp.Aspects;

namespace Core
{
    public delegate void PropertyBeforeChangeEventHandler(object sender, string sPropertyName, object oCurrentValue, ref object oProposedValue, ref bool bCancel);
    public delegate void PropertyAfterChangeEventHandler(object sender, string sPropertyName, object oOldValue, object oNewValue);

    public interface INotify
    {
        event PropertyBeforeChangeEventHandler PropertBeforeChange;
        event PropertyAfterChangeEventHandler PropertyAfterChange;
    }

    [Serializable]
    public sealed class NotifyAttribute : LocationInterceptionAspect, IInstanceScopedAspect
    {
        bool _NotifyBefore { get; set; }
        bool _NotifyAfter { get; set; }

        public NotifyAttribute() { _NotifyAfter = true; }
        public NotifyAttribute(bool bNotifyBefore, bool bNotifyAfter) { _NotifyBefore = bNotifyBefore; _NotifyAfter = bNotifyAfter; }

        public override void OnSetValue(LocationInterceptionArgs args)
        {
            INotify oNotify = args.Instance as INotify;
            if (oNotify == null) return;

            object oCurrentValue = args.GetCurrentValue();
            object oProposedValue = args.Value;
            if (object.Equals(oCurrentValue, oProposedValue)) return;
            bool bCancel = false;

            if (_NotifyBefore)
            {
                var oObj = args.Instance.GetType().GetEvent("PropertyBeforeChange");
                // RAISE EVENT HERE
            }
            if (bCancel) return;

            args.Value = oProposedValue;
            args.ProceedSetValue();
            if (_NotifyAfter)
            {
                var oObj = args.Instance.GetType().GetEvent("PropertyAfterChange");
                // RAISE EVENT HERE
            }
        }

        public object CreateInstance(AdviceArgs adviceArgs) { return this.MemberwiseClone(); }
        public void RuntimeInitializeInstance() { }
    }
}

having defined this interface and this attribute, i can use it as follows..

    public class Test : INotify
    {
        public event PropertyBeforeChangeEventHandler PropertyBeforeChange;
        public event PropertyAfterChangeEventHandler PropertyAfterChange;

        [Notify]
        public string Name { get; set; }
    }

    Test oTest = new Test();
    oTest.PropertyBeforeChange += Test_PropertBeforeChange;
    oTest.PropertyAfterChange += Test_PropertyAfterChange;
    oTest.Name = "Asim";
    void Test_PropertBeforeChange(object sender, string sPropertyName, object oCurrentValue, ref object oProposedValue, ref bool bCancel)
    {
    }
    void Test_PropertyAfterChange(object sender, string sPropertyName, object oOldValue, object oNewValue)
    {
    }
AweSIM
  • 1,651
  • 4
  • 18
  • 37
  • You are using PostSharp. Now you have two problems. Can you at least explain *why* you are using it? INotifyPropertyChange is a well established interface in .NET programming. – Hans Passant Jan 10 '13 at 22:48
  • Possible duplicate: http://stackoverflow.com/questions/198543/how-do-i-raise-an-event-via-reflection-in-net-c – e_ne Jan 10 '13 at 22:53
  • `INotifyPropertyChange` interface looks very much inadequate to me.. 1. it doesnt offer an event thats fired BEFORE a property is changed, so that the change can be cancelled / modified.. if you look at the `Test_PropertyBeforeChange()` handler below `oTest.Name = "Asim";` line, you can see it allows one to see both the current value, proposed value (which can be changed in the function) and a cancel flag (which can also be changed).. in the `OnSetValue()` function in `NotifyAttribute` class, these changed values are used for setting the property in question, or cancel the change entirely too. – AweSIM Jan 10 '13 at 22:57
  • (cont.) 2. the `INotifyPropertyChanged` interfaces forces the user to explicitely raise the `OnPropertyChanged` in every property's setter.. using a PostSharp attribute, i just need to mark a property with `[Notify]` attribute and it generates code to do that itself.. 3. the `EventArgs` that `INotifyPropertyChange` interfacce passes to a handler are extremely generic and contain little useful information.. sure i can use tricks to send in more data (property old and new values, etc) but having my own events with detailed information passed as local variables seems a better choice to me.. =) – AweSIM Jan 10 '13 at 23:03
  • i just need to understand how can i raise an event via reflection.. @Eve.. yes i did see the thread you linked.. i didnt understand how to implement in code what the accepted answer suggested.. for the answer below the accepted one, i didnt understand why i need Multicast delegates (or even what they are in the first place).. thats why im here for help.. =) – AweSIM Jan 10 '13 at 23:08
  • `System.ComponentModel.INotifyPropertyChanging` is intended for pre-change notifications. – Daniel Brückner Jan 10 '13 at 23:15
  • @DanielBrückner.. agreed but 1. it just notifies, instead of allowing to override the change or cancel it.. and 2. i really want to know how to raise an event via reflection.. i apologize if the code ive posted turned out to be a distraction from the actual issue at hand.. =( – AweSIM Jan 10 '13 at 23:27
  • @Eve.. actually youre right eve.. i saw that post countless times before posting here and didnt understand it.. i tried to understand it now and it makes sense.. i tried to use it to raise the events in question and it worked (which i never expected to).. thank you so much for the nudge.. =) – AweSIM Jan 10 '13 at 23:48

0 Answers0