Implémenter facilement inotifypropertychanged

Description

Ce petit bout de code montre comment implémenter INotifyPropertyChanged en ajoutant seulement un attribut personnalisé. Je l'ai écrit en C# 3.0, bien que seul le framework 2.0 est nécessaire à cette implémentation. Attention, le projet est un projet VS 2008.

Source / Exemple :


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using PostSharp.Laos;
using System.Text.RegularExpressions;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Test t = new Test();
            t.PropertyChanged += new PropertyChangedEventHandler((s, e) =>
            {
                Console.WriteLine(string.Format("{0} has changed", e.PropertyName));
            });

            t.Prop1 = "a value";
            t.Prop2 = "a value";
            t.Prop3 = "a value";
        }
    }

    [NotifyPropertyChanged]
    public class Test : INotifyPropertyChanged
    {
        public string Prop1 { get; set; }
        
        public string Prop2;

        private string _Prop3;

        public string Prop3
        {
            get { return _Prop3; }
            set { _Prop3 = value; }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }

    [Serializable]
    public class NotifyPropertyChanged : OnFieldAccessAspect
    {
        public override void OnSetValue(FieldAccessEventArgs eventArgs)
        {
            base.OnSetValue(eventArgs);
            
            var owner = eventArgs.Instance;

            string propertyName = string.Empty;
            string fieldName = eventArgs.FieldInfo.Name;
            Regex reg = new Regex(@"(<)(\w*?)(>k__BackingField)");
            Match match = reg.Match(fieldName);
            if (match.Success)
                propertyName = match.Groups[2].Value;
            else if(fieldName.StartsWith("~"))
                propertyName = fieldName.Replace("~", string.Empty);
            else if(fieldName.StartsWith("_"))
                propertyName = fieldName.Replace("_", string.Empty);

            var e = new PropertyChangedEventArgs(propertyName);

            FireEvent(owner, "PropertyChanged", e); 
        }

        //http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=776014&SiteID=1
        public void FireEvent(object owner, string name, EventArgs e)
        {
            MulticastDelegate eventDelagate =
                  (MulticastDelegate)owner.GetType().GetField(name,
                   System.Reflection.BindingFlags.Instance |
                   System.Reflection.BindingFlags.NonPublic).GetValue(owner);

            if (eventDelagate != null)
            {
                Delegate[] delegates = eventDelagate.GetInvocationList();

                foreach (Delegate dlg in delegates)
                    dlg.Method.Invoke(dlg.Target, new object[] { owner, e });
            }
        }    
    }
}

Conclusion :


Je me sert de PostSharp (http://www.postsharp.org/documentation/simple-trace-aspect-tutorial)
pour intercepter les "set" des propriétés.

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.