Is there a good strongly typed way to do PropertyChanged events in C#?

前端 未结 7 1080
轮回少年
轮回少年 2020-12-05 12:19

It must be a somewhat common event to change the name of a property and expect the Rename functionality in Visual Studio to take care of all the necessary renaming, except f

相关标签:
7条回答
  • 2020-12-05 12:36

    In theory, you could use MethodBase.GetCurrentMethod().Name.Substring(4) from within the property setter. Unfortunately, Google search reveals that it seems to have a significant performance impact. Two more things to consider:

    • JIT inlining can impact this in unexpected ways. (stackoverflow.com/questions/616779/can-i-check-if-the-c-compiler-inlined-a-method-call)
    • In theory, the IL call to MethodBase.GetCurrentMethod() could be trivially replaced by the JIT at runtime with a ldtoken instruction followed by a call to MethodBase.GetMethodFromHandle(), which would be very fast. I guess users just haven't expressed a need for this. (msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.ldtoken.aspx)
    • Completely my opinion here, but I think it'd be nice to have fieldof() and methodof() operators in C#. I believe it would greatly improve the reliability of the code analysis/refactoring tools in projects that require that ability.
    0 讨论(0)
  • 2020-12-05 12:37

    You should check out this blog post. It gives you the ability to do this:

    string propertyName = TypeHelper.GetPropertyName<User>(u => u.LastProjectCode);
    
    PropertyInfo property1 = TypeHelper.GetProperty((SomeClass o) => o.InstanceProperty.Length);
    
    PropertyInfo property2 = TypeHelper.GetProperty(() => SomeClass.StaticProperty.Length);
    

    Renames in Visual Studio/Resharper/Refactor Pro should work for you then.

    0 讨论(0)
  • 2020-12-05 12:40

    Edit: nameof arrived in c# 6. Yay!


    There is no nameof / infoof etc; this is much discussed, but it is what it is.

    There is a way to do it using lambda expressions in .NET 3.5 (and parsing the expression tree), but in reality it isn't worth the overhead. For now, I'd just stick with strings (and unit tests if you are determined not to break it).


    using System;
    using System.ComponentModel;
    using System.Linq.Expressions;
    using System.Reflection;
    class Program : INotifyPropertyChanged {
        public event PropertyChangedEventHandler PropertyChanged;
        static void Main() {
            var p = new Program();
            p.PropertyChanged += (s, a) => Console.WriteLine(a.PropertyName);
            p.Name = "abc";
        }
        protected void OnPropertyChanged<T>(Expression<Func<Program, T>> property) {
            MemberExpression me = property.Body as MemberExpression;
            if (me == null || me.Expression != property.Parameters[0]
                  || me.Member.MemberType != MemberTypes.Property) {
                throw new InvalidOperationException(
                    "Now tell me about the property");
            }
            var handler = PropertyChanged;
            if (handler != null) handler(this,
              new PropertyChangedEventArgs(me.Member.Name));
        }
        string name;
        public string Name {
            get{return name;}
            set {
                name = value;
                OnPropertyChanged(p=>p.Name);
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-05 12:41

    C# 5 seem to have a solution. With an CallerMemberName attribute that can be used with parameters (One example on the net).

    class Employee : INotifyPropertyChanged
    {
        private string _Name;
        public string Name
        {
            get { return _Name; }
    
            set
            {
                _Name = value;
                RaisePropertyChanged();
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        private void RaisePropertyChanged([CallerMemberName] string caller = "")
        {
            var temp = PropertyChanged;
    
            if ( temp != null )
            {
                temp( this, new PropertyChangedEventArgs( caller ) );
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-05 12:46

    Not an answer to your question, but if you right-click->Refactor->Rename a property, it can rename matching strings as well, including any strings that match your property's name.

    Yeah, it can be a bit dangerous.

    0 讨论(0)
  • 2020-12-05 12:46

    The PropertyChangedEventArgs only takes one constructor, which requires the property name as a string. So essentially no- utilizing INotifyPropertyChanged means that at some level, be it high or low in your architecture, you will have to work with a string and manual renaming.

    0 讨论(0)
提交回复
热议问题