749

Microsoft should have implemented something snappy for INotifyPropertyChanged, like in the automatic properties, just specify {get; set; notify;} I think it makes a lot of sense to do it. Or are there any complications to do it?

Can we ourselves implement something like 'notify' in our properties. Is there a graceful solution for implementing INotifyPropertyChanged in your class or the only way to do it is by raising the PropertyChanged event in each property.

If not can we write something to auto-generate the piece of code to raise PropertyChanged event?

Naser Asadi
  • 1,153
  • 18
  • 35
P.K
  • 18,587
  • 11
  • 45
  • 51
  • see http://stackoverflow.com/questions/1329138/how-to-make-databinding-type-safe-and-support-refactoring/1333874#1333874 for a compiler checked way of implementing INotifyPropertyChanged. Avoiding having the property names as a magic string. – Ian Ringrose Aug 26 '09 at 12:00
  • 8
    http://code.google.com/p/notifypropertyweaver/ may be of use – Ian Ringrose Feb 29 '12 at 11:36
  • 9
    above link is dead. https://github.com/SimonCropp/NotifyPropertyWeaver – prime23 Oct 18 '12 at 02:40
  • 1
    Despite having adequate alternatives, nothing for my team has been as painless as Postsharp's [Domain Toolkit](http://vimeo.com/49833062) (will be bundled with normal Postsharp in upcoming v3.0 I think). [NotifyPropertyChanged] on the class, [NotifyPropertyChangedIgnore] on the props to ignore. – Adam Caviness Jan 26 '13 at 04:51
  • @Codest and now your link is dead – joao2fast4u Mar 24 '16 at 15:33
  • 7
    @joao2fast4u https://github.com/Fody/PropertyChanged/wiki/ConvertingFromNotifyPropertyWeaver – prime23 Mar 25 '16 at 00:48
  • I agree with the OP here. It's really sad that this doesn't exist in Roslyn yet. Further there needs to be a way to notate that one property is dependent on the value of another (ideally with attributes, and the nameof operator). – BrainSlugs83 May 03 '16 at 19:35
  • 6
    At the time making changes to C# wasn't possible given we had a huge back log of inter-dependencies. So back when MVVM was born i guess, we just really didn't put to much effort into solving this issue and I know the Patterns & Practices team had a few goes at it along the way (hence you also got MEF as part of that research thread). Today i think [CallerMemberName] is the answer to the above. – Scott May 05 '16 at 02:32
  • I think @tom-gilder 's has a better answer. http://stackoverflow.com/a/18002490/4062881 – Vijay Chavda Feb 16 '17 at 17:16
  • `ObservableCollection` eliminates the need to implement `OnPropertyChanged`, for simple situations. See [How to: Create and Bind to an ObservableCollection](https://learn.microsoft.com/en-us/dotnet/framework/wpf/data/how-to-create-and-bind-to-an-observablecollection), and [ObservableCollection](https://msdn.microsoft.com/en-us/library/ms668604%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396). – ToolmakerSteve Dec 23 '17 at 00:15

35 Answers35

745

Without using something like postsharp, the minimal version I use uses something like:

public class Data : INotifyPropertyChanged
{
    // boiler-plate
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
    protected bool SetField<T>(ref T field, T value, string propertyName)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }

    // props
    private string name;
    public string Name
    {
        get { return name; }
        set { SetField(ref name, value, "Name"); }
    }
}

Each property is then just something like:

private string name;
public string Name
{
    get { return name; }
    set { SetField(ref name, value, "Name"); }
}

which isn't huge; it can also be used as a base-class if you want. The bool return from SetField tells you if it was a no-op, in case you want to apply other logic.


or even easier with C# 5:

protected bool SetField<T>(ref T field, T value,
    [CallerMemberName] string propertyName = null)
{...}

which can be called like this:

set { SetField(ref name, value); }

with which the compiler will add the "Name" automatically.


C# 6.0 makes the implementation easier:

protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

...and now with C#7:

protected void OnPropertyChanged(string propertyName)
   => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

protected bool SetField<T>(ref T field, T value,[CallerMemberName] string propertyName =  null)
{
    if (EqualityComparer<T>.Default.Equals(field, value)) return false;
    field = value;
    OnPropertyChanged(propertyName);
    return true;
}

private string name;
public string Name
{
    get => name;
    set => SetField(ref name, value);
}

And, with C# 8 and Nullable reference types, it would look like this:

public event PropertyChangedEventHandler? PropertyChanged;

protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = "")
{
    if (EqualityComparer<T>.Default.Equals(field, value)) return false;
    field = value;
    OnPropertyChanged(propertyName);
    return true;
}

private string name;
public string Name
{
    get => name;
    set => SetField(ref name, value);
}
Mike Christiansen
  • 1,104
  • 2
  • 13
  • 30
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 5
    Nice trick Marc ! I suggested an improvement to use a lambda expression instead of the property name, see my answer – Thomas Levesque Aug 22 '09 at 17:50
  • 3
    DevXpress Xpo does it this way. – Anton Tykhyy Aug 22 '09 at 17:54
  • 12
    @Thomas - the lambda is all well and good, but it adds a lot of overhead for something that is actually very simple. A handy trick, but I'm not sure it is always practical. – Marc Gravell Aug 22 '09 at 19:38
  • 17
    @Marc - Yes, it can probably degrade performance... However I really like the fact that it's checked at compile time, and is correctly refactored by the "Rename" command – Thomas Levesque Aug 22 '09 at 21:23
  • 1
    @PKKG that means nobody has subscribed to the event – Marc Gravell Jul 24 '13 at 09:03
  • 2
    What about: private void RaisePropertyChanged( [CallerMemberName] string caller = "") { if ( PropertyChanged != null ) { PropertyChanged( this, new PropertyChangedEventArgs( caller ) ); } } – Pedro77 Oct 07 '13 at 17:45
  • @ThomasLevesque The refactor ability supersedes the performance hit imo. Never pre-optimise where sacrificing maintainability is concerned. – Gusdor Oct 22 '13 at 07:29
  • 7
    @Gusdor fortunately, with C#5 there is no need to compromise - you can get the best of both via (as Pedro77 notes) `[CallerMemberName]` – Marc Gravell Oct 22 '13 at 08:30
  • 1
    @MarcGravell I wish I could know this joy. I'm still supporting windows XP and have to use .Net 4 :*( – Gusdor Oct 22 '13 at 08:37
  • 6
    @Gusdor the language and framework are separate; you can use the C# 5 compiler, target .NET 4, and just **add the missing attribute yourself** - it will work fine. It just has to have the correct name and be in the correct namespace. It does not need to be in a specific assembly. – Marc Gravell Oct 22 '13 at 08:39
  • 1
    In case reflection is not an Issue in , one can use `MethodBase.GetCurrentMethod().Name.Substring(4);` instead of writing the Property name every time. the 4 is to trim the `"set_"` string. I know, it is ugly... – itsho Dec 17 '13 at 15:24
  • 2
    @Gusdor [CallerMemberName] is available for .Net 4.0 using the Microsoft.Bcl nuget package! http://www.nuget.org/packages/Microsoft.Bcl/ – Zachary Yates Apr 22 '14 at 18:28
  • Is it possible to write an intermediate parent class that exposes the PropertyChagned event and implements SetField<>? It seems like a code smell to have this method defined in every class that implements INotifyPropertyChanged. Likewise, can we not squeeze out the "notifying public property" idiom somehow? – Jay Carlton Sep 29 '14 at 20:39
  • @Jay there are ways of doing it with static methods so that you only need to declare it once, sure – Marc Gravell Sep 29 '14 at 21:05
  • I just noticed `BindableBase` does what I was looking for. Thanks, @Marc. – Jay Carlton Oct 01 '14 at 03:00
  • 1
    What black magic is this? Can somebody point to some reference or explanation? What is `[CallerMemberName]` and `PropertyChanged?.Invoke`? – Fandi Susanto Dec 09 '15 at 13:49
  • 2
    @FandiSusanto `[CallerMemberName]` is a parameter attribute that the C# 5 compiler recognizes, and automatically injects the name of the calling method/member (as a constant string, so interned, etc); The `?.` syntax is C# 6 for `null` propagation; if the object on the left is non-`null`, the method will be invoked; if the object is null,it won't. If there was a return value implied, it would assume the value `null` if the object was `null`. – Marc Gravell Dec 09 '15 at 14:39
  • 1
    @MarcGravell perhaps you could clean up the code for C# 6, so [this](http://stackoverflow.com/questions/35582162/how-to-implement-inotifypropertychanged-in-c-sharp-6-0/) can be avoided? I now regret answering instead of voting to close – Panagiotis Kanavos Feb 24 '16 at 08:48
  • Downvoted. This is not automatic. -- Even the recommended way in C# 5 is lame. C# 6 adds a whole slew of built-in ways to do cool things with properties -- but not this, and it's a shame. – BrainSlugs83 May 03 '16 at 19:36
  • 1
    @BrainSlugs83 which bit is "not automatic"? There's actually something very interesting being discussed in C# 7 which may do what you want, but right now, *without using additional tools* (like postsharp), this is about the simplest you'll get. – Marc Gravell May 03 '16 at 20:56
  • I think an even better variation in C# 6 would be to call PropertyChanged directly from the setter of an attribute: `PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CallingAttribute)));` – Stanislav Jun 09 '16 at 07:12
  • Re: the C#6 example- It's occasionally useful to pass `null` as the argument to the `PropertyChanged` event (to indicate that _all_ properties on the object have changed). Thus, it might still be valuable to utilize a separate `SetField` method just so that `OnPropertyChanged` can be explicitly called with `null` for this purpose. – jmbpiano Aug 26 '16 at 15:18
  • 1
    @MarcGravell I'd suggest an even shorter way. Yet another answer won't be read and it's in part had been suggested below, but, to summarize, I declare any property as follows: `public string MyProp { get { return Get(); } set { Set(value); } }`. The benefit is it's shorter (a one-liner if you wish) and it can be blindly copied without changing to make any property bindable. No backing fields also. The downside - having a base class. The trick is to make Get return `dynamic` and Set take `object`. And no, this does not slow down your app in any significant way. But it does speed up the dev. – evilkos Oct 19 '16 at 11:16
  • What's the reasoning for your `SetField` method using `EqualityComparer.Default.Equals(field, value)` rather than just `field == value`? Is this just to better support the case where type `T` has been implemented poorly? – Adam Goodwin Oct 24 '16 at 05:25
  • @AdamGoodwin generics do not work with operators like `==` – Marc Gravell Oct 24 '16 at 10:23
  • Oops, I knew it would be something obvious – I should have just tried it. – Adam Goodwin Oct 24 '16 at 10:25
  • is there a way to not write that boilerplate in every new class i create ?? – bh_earth0 Nov 03 '17 at 08:38
  • 1
    Furthermore in C# 6.0 you can use expression body notation: `protected void OnPropertyChanged( [CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));` – brakeroo Nov 17 '17 at 15:46
  • And for C#7 we can skip the nameof(Name) param to make it a little shorter. – Andrey Klochkov Apr 25 '18 at 09:30
  • @AndreyKlochkov you're right - fixed; looks like that segment was added at a later date, but: all fixed – Marc Gravell Apr 25 '18 at 10:46
  • Out of interest: why `SetField` and not `SetProperty`? – JDR Sep 24 '18 at 07:34
  • 1
    @JDR because it takes, and assigns to, a reference to a field - not a reference to a property (there is no such thing as a reference to a property, unless you count `ref return` which is new) – Marc Gravell Sep 24 '18 at 08:45
  • I've recently started to incorporate bellow check into the SetField method. I often copy and paste the code into a class and forget to inherit INotifyPropertyChanged. This gives me a clear reminder. `if (this != null && !(this is INotifyPropertyChanged)) { throw new Exception("Forgot to inherit INotifyPropertyChanged"); }` – fstam Nov 09 '18 at 07:30
  • should the c# & code be: set => SetField(ref name, value, "name"); – Mark Redman Dec 01 '18 at 19:16
  • @MarkRedman no; the whole point of `[CallerMemberName]` is that it provides the caller name automatically – Marc Gravell Dec 03 '18 at 10:55
  • @MarcGravell, ok, makes sense, was sure I am am C#7, but indicated a missing parameter... – Mark Redman Dec 03 '18 at 10:57
  • @MarkRedman that's odd - just to be sure, I did test it here before I replied, and it compiled fine – Marc Gravell Dec 03 '18 at 11:07
  • This could probably benefit from C#8's upcoming default interface implementations. That way a lot of the boilerplate could possibly be moved into the interface declaration. – JAD Feb 04 '19 at 08:12
  • 3
    This is pretty cool. However, in MVVM, the pattern is usually, in my experience, that the ViewModel wraps a model. So there is no backing field. Instead we need to set model.Name to a value. We can't pass model.Name in as a ref. – Rhyous Mar 16 '19 at 22:39
  • I found this absolutely great until I noticed that I do not have the new value on the event PropertyChanged. the field = value somehow does not happen / the field has not been updated in the class where i implemented this (and assigned an event where i want to work with the new value) – t0b4cc0 Jun 03 '20 at 13:26
  • @t0b4cc0 that probably means that your `IEquatable` implementation isn't right - see where we short-circuit if the two values are equal, at `if (EqualityComparer.Default.Equals(field, value))` - this uses `IEquatable`, or regular `Equals(object)` if that isn't available – Marc Gravell Jun 03 '20 at 13:29
  • @MarcGravell thank you for the quick reply! I do not implement IEquatable myself so it defaults. I should clarify the issue: The two values are not equal. The line `field = value;` does happen but I can not retrieve that new value in the class I implemented the interface AND the function I put onto the event handler. Just after the `field = value;` the `OnPropertyChanged` will be called. I assign an event to that (in the class where the field lives) but the Field will not have the new value there. If this is not intended behavior I will start a new topic. – t0b4cc0 Jun 03 '20 at 13:47
  • @t0b4cc0 I'd probably need to see it in context as a repro to understand exactly what your scenario is – Marc Gravell Jun 03 '20 at 14:10
  • @MarcGravell It works perfect in another other class. I moved my code from on property changed between the brakets in the `if(SetField(...,..)){//my property changed code}` because ofc a test version should be here yesterday :) I will probably start anew topic if this becomes relevant for me again – t0b4cc0 Jun 03 '20 at 14:42
  • C#9 allows the `new PropertyChangedEventArgs(propertyName)` expression to be shortened to just `new(propertyName)`. – Bill Menees Mar 31 '21 at 19:33
206

.Net 4.5 introduced Caller Information Attributes:

private void OnPropertyChanged<T>([CallerMemberName]string caller = null) {
     // make sure only to call this if the value actually changes

     var handler = PropertyChanged;
     if (handler != null) {
        handler(this, new PropertyChangedEventArgs(caller));
     }
}

It's probably a good idea to add a comparer to the function as well.

EqualityComparer<T>.Default.Equals

More examples here and here

Also see Caller Information (C# and Visual Basic)

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
Daniel Little
  • 16,975
  • 12
  • 69
  • 93
  • 14
    Brilliant! But why is it generic? – abatishchev Dec 12 '12 at 18:40
  • @abatishchev I guess it doesn't have to be, I was just playing with the idea of having the function set the property as well. I'll see if I can update my answer provide the full solution. The extra examples do a good job that in the meantime. – Daniel Little Dec 13 '12 at 00:06
  • 3
    It was introduced by C # 5.0. It has nothing to do with .net 4.5, but this is a great solution! – J. Lennon Feb 17 '13 at 23:20
  • 6
    @J. Lennon .net 4.5 still has something to do with it, after all the attribute comes from somewhere http://msdn.microsoft.com/en-au/library/system.runtime.compilerservices.callermembernameattribute.aspx – Daniel Little Feb 17 '13 at 23:43
  • @Lavinski change your application to eg .NET 3.5 and see what will work (in vs2012) – J. Lennon Feb 18 '13 at 00:23
  • @Lavinski sorry, I was wrong. CallerMemberName was introduced by other implementations for older versions of .NET (async bridge and microsoft.bcl) – J. Lennon Feb 18 '13 at 00:35
  • @Lavinski It *is* possible to use this while targeting older framework versions, with a minor tweak: http://stackoverflow.com/a/13382257/1030702 – Bob Jun 13 '13 at 02:10
  • A great approach, but it does have some shortcomings: http://awkwardcoder.blogspot.co.uk/2012/07/callermembername-not-that-great-for.html – Cocowalla Jul 01 '13 at 11:07
  • Is there a neat way to use this when you just have public getters and are using private setters with a ChangeMyProperty(string value) type of method call to follow a more DDD pattern? I assume [CallerMemberName] will report incorrectly with this approach? – Dib Jun 18 '15 at 06:42
170

I really like Marc's solution, but I think it can be slightly improved to avoid using a "magic string" (which doesn't support refactoring). Instead of using the property name as a string, it's easy to make it a lambda expression :

private string name;
public string Name
{
    get { return name; }
    set { SetField(ref name, value, () => Name); }
}

Just add the following methods to Marc's code, it will do the trick :

protected virtual void OnPropertyChanged<T>(Expression<Func<T>> selectorExpression)
{
    if (selectorExpression == null)
        throw new ArgumentNullException("selectorExpression");
    MemberExpression body = selectorExpression.Body as MemberExpression;
    if (body == null)
        throw new ArgumentException("The body must be a member expression");
    OnPropertyChanged(body.Member.Name);
}

protected bool SetField<T>(ref T field, T value, Expression<Func<T>> selectorExpression)
{
    if (EqualityComparer<T>.Default.Equals(field, value)) return false;
    field = value;
    OnPropertyChanged(selectorExpression);
    return true;
}

BTW, this was inspired by this blog post.

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • 7
    There's at least one framework using this method, [ReactiveUI](http://www.reactiveui.net). – AlSki Oct 11 '11 at 16:19
  • 1
    Very late, this meant going through reflection, which meant a performance hit. It could be acceptable, but setting a property isn't a place where I'd like my application to spend to many cycles. – Bruno Brant Feb 26 '15 at 19:46
  • 2
    @BrunoBrant Are you sure there is a performance hit? According to the blog post the reflection happens during compile time rather than runtime (i.e. static reflection). – Nathaniel Elkins Mar 17 '15 at 21:47
  • 1
    @NathanielElkins you are correct. I was remembering that I actually had a performance hit when using expressions, but the reason for that is that I needed to compile the expression afterwards. One more tip: this fails if the users points to a property on a sublevel, ie, "foo.bar.baz". You can expand the algorithm to cover that. – Bruno Brant Apr 18 '15 at 19:35
  • 8
    I believe your whole OnPropertyChanged is obsolete with the nameof operator of C# 6, making this monster a bit sleeker. – ASA May 01 '15 at 18:04
  • 8
    @Traubenfuchs, actually, C#5's CallerMemberName attribute makes it even simpler, since you don't need to pass anything at all ... – Thomas Levesque May 02 '15 at 00:02
  • Though this has been since superseded by C# improvements it was a very cool approach! – StayOnTarget Mar 03 '23 at 14:00
142

There's also Fody which has a AddINotifyPropertyChangedInterface add-in, which lets you write this:

[AddINotifyPropertyChangedInterface]
public class Person 
{        
    public string GivenNames { get; set; }
    public string FamilyName { get; set; }
}

...and at compile time injects property changed notifications.

birgersp
  • 3,909
  • 8
  • 39
  • 79
Tom Gilder
  • 1,079
  • 1
  • 13
  • 21
  • 9
    I think this is exactly what OP was looking for when they asked "Can we ourselves implement something like 'notify' in our properties. Is there a graceful solution for implementing INotifyPropertyChanged in your class" – Ashoat Aug 05 '16 at 06:59
  • 3
    This is the only graceful solution really, and it does work flawlessly as @CADbloke said. And I was skeptic about the weaver as well, but I checked/rechecked the IL code behind and it's perfect, it's simple, does all you need and none else. It also hooks and calls whatever method name you have designated in the base class for it, whether NotifyOnProp..., OnNotify... doesn't matter, so works well with any base class that you might have and that implements INotify... – NSGaga-mostly-inactive Mar 04 '17 at 22:04
  • 2
    You can easily double-check what the weaver is doing, have a look at the build output window, it lists all the PropertyChanged things it has weaved. Using the VScolorOutput extension with the regex pattern `"Fody/.*?:",LogCustom2,True` highlights it in the "Custom 2" color. I made it bright pink so it's easy to find. Just Fody everything, it's the neatest way to do anything that has lots of repetitive typing. – CAD bloke Jul 25 '17 at 04:28
  • @mahmoudnezarsarhan no, it's not, I remember there was a slight change in the way it has to be configured, but [Fody PropertyChanged](https://github.com/Fody/PropertyChanged) is still alive and active. – Larry Jul 23 '19 at 12:50
  • 1
    It does seem to have been removed from Fody – Damien Dec 01 '20 at 08:21
  • 1
    I agree @Damien. As of version [3.4.0](https://www.nuget.org/packages/PropertyChanged.Fody) this property is deprecated. using the `AddINotifyPropertyChangedInterfaceAttribute`, as recommended by documentation, works for me. – Examath Nov 13 '21 at 09:18
71

I think people should pay a little more attention to performance; it really does impact the UI when there are a lot of objects to be bound (think of a grid with 10,000+ rows), or if the object's value changes frequently (real-time monitoring app).

I took various implementation found here and elsewhere and did a comparison; check it out perfomance comparison of INotifyPropertyChanged implementations.


Here is a peek at the result Implemenation vs Runtime

Sabuncu
  • 5,095
  • 5
  • 55
  • 89
Peijen
  • 83
  • 2
  • 6
  • 16
    -1 : there is no performance overhead : CallerMemberName are changed into literal values at compile time. Just try and decompile your app. – JYL Mar 17 '14 at 00:11
  • here is the according question and answer: http://stackoverflow.com/questions/22580623/inotifypropertychanged-is-callermembername-slow-compared-to-alternatives – uli78 Mar 25 '14 at 13:47
  • 1
    @JYL, you are correct that CallerMemberName did not add a large overhead. I must have implemented something wrong last time I tried it. I will update the blog and answer to reflect the benchmark for CallerMemberName and Fody implementation later. – Peijen Apr 22 '14 at 05:43
  • 1
    If you have a grid of 10,000+ in the UI then you should probably be combining approaches to handle performance, like paging where you only show 10, 50, 100, 250 hits per page... – Austin Rhymer Jul 19 '17 at 15:06
  • 1
    Austin Rhymer , if you have larg data + 50 use data virtualisation no need to load all data it will load only the data that is visible on the current scolling displayed area ! – Bilal May 05 '20 at 00:17
  • The link is dead, so this is no longer useful. – StayOnTarget Mar 03 '23 at 14:01
40

I introduce a Bindable class in my blog at http://timoch.com/blog/2013/08/annoyed-with-inotifypropertychange/ Bindable uses a dictionary as a property bag. It's easy enough to add the necessary overloads for a subclass to manage its own backing field using ref parameters.

  • No magic string
  • No reflection
  • Can be improved to suppress the default dictionary lookup

The code:

public class Bindable : INotifyPropertyChanged {
    private Dictionary<string, object> _properties = new Dictionary<string, object>();

    /// <summary>
    /// Gets the value of a property
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="name"></param>
    /// <returns></returns>
    protected T Get<T>([CallerMemberName] string name = null) {
        Debug.Assert(name != null, "name != null");
        object value = null;
        if (_properties.TryGetValue(name, out value))
            return value == null ? default(T) : (T)value;
        return default(T);
    }

    /// <summary>
    /// Sets the value of a property
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <param name="name"></param>
    /// <remarks>Use this overload when implicitly naming the property</remarks>
    protected void Set<T>(T value, [CallerMemberName] string name = null) {
        Debug.Assert(name != null, "name != null");
        if (Equals(value, Get<T>(name)))
            return;
        _properties[name] = value;
        OnPropertyChanged(name);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

It can be used like this:

public class Contact : Bindable {
    public string FirstName {
        get { return Get<string>(); }
        set { Set(value); }
    }
}
TiMoch
  • 1,008
  • 1
  • 10
  • 17
  • 2
    This is a nice solution, but the only downside is that there's a small performance hit involving boxing / unboxing. – MCattle Oct 17 '14 at 21:57
  • @MCattle if we are down to measuring the impact of boxing/unboxing, then we may as well remove the usage of the dictionary and provide Get/Set signatures that take a ref backing field. We may as well provide the means for caching PropertyChangedEventArgs objects – TiMoch Oct 22 '14 at 09:58
  • 1
    I would suggest to use `protected T Get(T defaultValue, [CallerMemberName] string name = null)` and also check `if (_properties.ContainsKey(name) && Equals(value, Get(default(T), name)))` in Set (to raise & save when first set to default value) – Miquel Feb 12 '15 at 02:35
  • +1 for a great solution! I wish I had discovered this answer sooner. Incidentally, quite a few related concerns can be solved much easier with a dictionary-based `INotifyPropertyChanged` than if each property had its own backing field: for example, creating & restoring object snapshots (think `IEditableObject`). – stakx - no longer contributing Feb 28 '15 at 01:34
  • 1
    @Miquel adding support for custom default values can be useful for sure, however you should be careful to only raise the changed event when the value actually changed. Setting a property to the same value it had should not raise events. I must admit in most cases it's harmless, howeverI've been bit quite a few times with properties being set thousands of time to the same value with events destroying UI responsiveness. – TiMoch Mar 01 '15 at 20:14
  • 1
    @stakx I have a few applications that build on this to support the memento pattern for undo/redo or to enable the unit of work pattern in applications where nhibernate isn't usable – TiMoch Mar 01 '15 at 20:16
  • 1
    I really like this particular solution: short notation, no dynamic proxy stuff, no IL-meddling, etc. Although, **you can make it shorter** by removing the need to specify T every time for Get by making Get return dynamic. I know, this impacts runtime performance, but now the code for getters and setters can finally be **always the same and in one line**, praise the Lord! P.S. you should take additional care inside your Get method (one time when you write the base class) when returning default values for valuetypes as dynamic. Be sure to always return correct default values (it can be done) – evilkos Feb 05 '16 at 09:31
  • Very interesting approach to prevent the burden of backing fields, thanks. – AFract Nov 07 '19 at 08:51
17

I haven't actually had a chance to try this myself yet, but next time I'm setting up a project with a big requirement for INotifyPropertyChanged I'm intending on writing a Postsharp attribute that will inject the code at compile time. Something like:

[NotifiesChange]
public string FirstName { get; set; }

Will become:

private string _firstName;

public string FirstName
{
   get { return _firstname; }
   set
   {
      if (_firstname != value)
      {
          _firstname = value;
          OnPropertyChanged("FirstName")
      }
   }
}

I'm not sure if this will work in practice and I need to sit down and try it out, but I don't see why not. I may need to make it accept some parameters for situations where more than one OnPropertyChanged needs to be triggered (if, for example, I had a FullName property in the class above)

Currently I'm using a custom template in Resharper, but even with that I'm getting fed up of all my properties being so long.


Ah, a quick Google search (which I should have done before I wrote this) shows that at least one person has done something like this before here. Not exactly what I had in mind, but close enough to show that the theory is good.

Martin Harris
  • 28,277
  • 7
  • 90
  • 101
  • 7
    A free tool called Fody seems to do the same thing, functioning as a generic compile-time code injector. It's downloadable in Nuget, as are its PropertyChanged and PropertyChanging plugin packages. – Triynko Feb 10 '14 at 20:39
13

Yes, better way certainly exists. Here it is:

Step by step tutorial shrank by me, based on this useful article.

  • Create new project
  • Install castle core package into the project

Install-Package Castle.Core

  • Install mvvm light libraries only

Install-Package MvvmLightLibs

  • Add two classes in project:

NotifierInterceptor

public class NotifierInterceptor : IInterceptor
    {
        private PropertyChangedEventHandler handler;
        public static Dictionary<String, PropertyChangedEventArgs> _cache =
          new Dictionary<string, PropertyChangedEventArgs>();

        public void Intercept(IInvocation invocation)
        {
            switch (invocation.Method.Name)
            {
                case "add_PropertyChanged":
                    handler = (PropertyChangedEventHandler)
                              Delegate.Combine(handler, (Delegate)invocation.Arguments[0]);
                    invocation.ReturnValue = handler;
                    break;
                case "remove_PropertyChanged":
                    handler = (PropertyChangedEventHandler)
                              Delegate.Remove(handler, (Delegate)invocation.Arguments[0]);
                    invocation.ReturnValue = handler;
                    break;
                default:
                    if (invocation.Method.Name.StartsWith("set_"))
                    {
                        invocation.Proceed();
                        if (handler != null)
                        {
                            var arg = retrievePropertyChangedArg(invocation.Method.Name);
                            handler(invocation.Proxy, arg);
                        }
                    }
                    else invocation.Proceed();
                    break;
            }
        }

        private static PropertyChangedEventArgs retrievePropertyChangedArg(String methodName)
        {
            PropertyChangedEventArgs arg = null;
            _cache.TryGetValue(methodName, out arg);
            if (arg == null)
            {
                arg = new PropertyChangedEventArgs(methodName.Substring(4));
                _cache.Add(methodName, arg);
            }
            return arg;
        }
    }

ProxyCreator

public class ProxyCreator
{
    public static T MakeINotifyPropertyChanged<T>() where T : class, new()
    {
        var proxyGen = new ProxyGenerator();
        var proxy = proxyGen.CreateClassProxy(
          typeof(T),
          new[] { typeof(INotifyPropertyChanged) },
          ProxyGenerationOptions.Default,
          new NotifierInterceptor()
          );
        return proxy as T;
    }
}
  • Create your view model, for example:

-

 public class MainViewModel
    {
        public virtual string MainTextBox { get; set; }

        public RelayCommand TestActionCommand
        {
            get { return new RelayCommand(TestAction); }
        }

        public void TestAction()
        {
            Trace.WriteLine(MainTextBox);
        }
    }
  • Put bindings into xaml:

    <TextBox Text="{Binding MainTextBox}" ></TextBox>
    <Button Command="{Binding TestActionCommand}" >Test</Button>
    
  • Put line of code in code-behind file MainWindow.xaml.cs like this:

DataContext = ProxyCreator.MakeINotifyPropertyChanged<MainViewModel>();

  • Enjoy.

enter image description here

Attention!!! All bounded properties should be decorated with keyword virtual because they used by castle proxy for overriding.

Kols
  • 3,641
  • 2
  • 34
  • 42
testCoder
  • 7,155
  • 13
  • 56
  • 75
  • I'm interested to know which version of Castle you are using. I am using 3.3.0 and the CreateClassProxy method does not have those parameters: `type`, `interfaces to apply`, `interceptors`. – IAbstract Apr 13 '16 at 21:56
  • Nevermind, I was using the generic `CreateClassProxy` method. Much different ...hmmm, wondering why so limited with the generic method. :( – IAbstract Apr 13 '16 at 22:25
8

A very AOP-like approach is to inject the INotifyPropertyChanged stuff onto an already instantiated object on the fly. You can do this with something like Castle DynamicProxy. Here is an article that explains the technique:

Adding INotifyPropertyChanged to an existing object

Kols
  • 3,641
  • 2
  • 34
  • 42
HokieMike
  • 655
  • 1
  • 7
  • 17
8

It's 2022. Now there's an official solution.

Use the MVVM source generators in Microsoft MVVM Toolkit.

This

[ObservableProperty]
private string? name;

will generate:

private string? name;

public string? Name
{
    get => name;
    set
    {
        if (!EqualityComparer<string?>.Default.Equals(name, value))
        {
            OnNameChanging(value);
            OnPropertyChanging();
            name = value;
            OnNameChanged(value);
            OnPropertyChanged();
        }
    }
}

// Property changing / changed listener
partial void OnNameChanging(string? value);
partial void OnNameChanged(string? value);

protected void OnPropertyChanging([CallerMemberName] string? propertyName = null)
{
    PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(propertyName));
}

protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

It supports .NET standard 2.0 and .NET >= 5.0.

John
  • 66
  • 2
  • 5
  • What is quite pain with this generator is that you have to change your properties to fields. In our large project it took me a while. – Kebechet Dec 14 '22 at 21:49
  • Yet another workaround for something that shouldn't require it, but this time with tons of magic :| – t3chb0t Mar 01 '23 at 20:09
  • 1
    @t3chb0t It's not exactly "tons of magic". The partial classes which are generated are easy to see. It's just using an attribute to generate the equivalent public properties from your private fields, and shoving all that boilerplate in a partial class. – WSC Mar 28 '23 at 13:56
  • 1
    @WSC the language should be designed in such a way that it doesn't require generating code and partial classes for _obvious_ and _natural_ design patterns. – t3chb0t Mar 28 '23 at 16:09
5

Look here : http://dotnet-forum.de/blogs/thearchitect/archive/2012/11/01/die-optimale-implementierung-des-inotifypropertychanged-interfaces.aspx

It's written in German, but you can download the ViewModelBase.cs. All the comments in the cs-File are written in English.

With this ViewModelBase-Class it is possible to implement bindable properties similar to the well known Dependency Properties :

public string SomeProperty
{
    get { return GetValue( () => SomeProperty ); }
    set { SetValue( () => SomeProperty, value ); }
}
mbinette
  • 5,094
  • 3
  • 24
  • 32
5

All these answer are very nice.

My solution is using the code snippets to do the job.

This uses the simplest call to PropertyChanged event.

Save this snippet and use it as you use 'fullprop' snippet.

the location can be found at 'Tools\Code Snippet Manager...' menu at Visual Studio.

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>inotifypropfull</Title>
            <Shortcut>inotifypropfull</Shortcut>
            <HelpUrl>http://ofirzeitoun.wordpress.com/</HelpUrl>
            <Description>Code snippet for property and backing field with notification</Description>
            <Author>Ofir Zeitoun</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>type</ID>
                    <ToolTip>Property type</ToolTip>
                    <Default>int</Default>
                </Literal>
                <Literal>
                    <ID>property</ID>
                    <ToolTip>Property name</ToolTip>
                    <Default>MyProperty</Default>
                </Literal>
                <Literal>
                    <ID>field</ID>
                    <ToolTip>The variable backing this property</ToolTip>
                    <Default>myVar</Default>
                </Literal>
            </Declarations>
            <Code Language="csharp">
                <![CDATA[private $type$ $field$;

    public $type$ $property$
    {
        get { return $field$;}
        set { 
            $field$ = value;
            var temp = PropertyChanged;
            if (temp != null)
            {
                temp(this, new PropertyChangedEventArgs("$property$"));
            }
        }
    }
    $end$]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

You can modify the call as you like (to use the above solutions)

Ofir
  • 2,174
  • 1
  • 16
  • 15
5

Whilst there are obviously lots of ways to do this, with the exception of the AOP magic answers, none of the answers seem to look at setting a Model's property directly from the view model without having a local field to reference.

The issue is you can't reference a property. However, you can use an Action to set that property.

protected bool TrySetProperty<T>(Action<T> property, T newValue, T oldValue, [CallerMemberName] string propertyName = null)
{
    if (EqualityComparer<T>.Default.Equals(oldValue, newValue))
    {
        return false;
    }

    property(newValue);
    RaisePropertyChanged(propertyName);
    return true;
}

This can be used like the following code extract.

public int Prop {
    get => model.Prop;
    set => TrySetProperty(x => model.Prop = x, value, model.Prop);
}

Check out this BitBucket repo for a full implementation of the method and a few different ways of achieving the same result, including a method that uses LINQ and a method that uses reflection. Do note that these methods are slower performance wise.

Dan
  • 7,286
  • 6
  • 49
  • 114
  • I've been looking for this. Thanks for sharing your implementation. Are you still using this method? – GisMofx Aug 29 '20 at 16:34
  • @GisMofx I haven't really done much WPF development recently but in my last WPF project, I did use this method, along with some of the others in [NotifyPropertyChange](https://bitbucket.org/DanJBower/wpf-binder/src/master/WPF%20Binder/WPF%20Binder/Utility/NotifyPropertyChange.cs) from my repo that I linked – Dan Sep 01 '20 at 19:46
5

Let me introduce my own approach called Yappi. It belongs to Runtime proxy|derived class generators, adding new functionality to an existing object or type, like Caste Project's Dynamic Proxy.

It allows to implement INotifyPropertyChanged once in base class, and then declare derived classes in following style, still supporting INotifyPropertyChanged for new properties:

public class Animal:Concept
{
    protected Animal(){}
    public virtual string Name { get; set; }
    public virtual int Age { get; set; }
}

Complexity of derived class or proxy construction can be hidden behind the following line:

var animal = Concept.Create<Animal>.New();

And all INotifyPropertyChanged implementation work can be done like this:

public class Concept:INotifyPropertyChanged
{
    //Hide constructor
    protected Concept(){}

    public static class Create<TConcept> where TConcept:Concept
    {
        //Construct derived Type calling PropertyProxy.ConstructType
        public static readonly Type Type = PropertyProxy.ConstructType<TConcept, Implementation<TConcept>>(new Type[0], true);
        //Create constructing delegate calling Constructor.Compile
        public static Func<TConcept> New = Constructor.Compile<Func<TConcept>>(Type);
    }


    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(PropertyChangedEventArgs eventArgs)
    {
        var caller = PropertyChanged;
        if(caller!=null)
        {
            caller(this, eventArgs);
        }
    }

    //define implementation
    public class Implementation<TConcept> : DefaultImplementation<TConcept> where TConcept:Concept
    {
        public override Func<TBaseType, TResult> OverrideGetter<TBaseType, TDeclaringType, TConstructedType, TResult>(PropertyInfo property)
        {
            return PropertyImplementation<TBaseType, TDeclaringType>.GetGetter<TResult>(property.Name);
        }
        /// <summary>
        /// Overriding property setter implementation.
        /// </summary>
        /// <typeparam name="TBaseType">Base type for implementation. TBaseType must be TConcept, and inherits all its constraints. Also TBaseType is TDeclaringType.</typeparam>
        /// <typeparam name="TDeclaringType">Type, declaring property.</typeparam>
        /// <typeparam name="TConstructedType">Constructed type. TConstructedType is TDeclaringType and TBaseType.</typeparam>
        /// <typeparam name="TResult">Type of property.</typeparam>
        /// <param name="property">PropertyInfo of property.</param>
        /// <returns>Delegate, corresponding to property setter implementation.</returns>
        public override Action<TBaseType, TResult> OverrideSetter<TBaseType, TDeclaringType, TConstructedType, TResult>(PropertyInfo property)
        {
            //This code called once for each declared property on derived type's initialization.
            //EventArgs instance is shared between all events for each concrete property.
            var eventArgs = new PropertyChangedEventArgs(property.Name);
            //get delegates for base calls.
            Action<TBaseType, TResult> setter = PropertyImplementation<TBaseType, TDeclaringType>.GetSetter<TResult>(property.Name);
            Func<TBaseType, TResult> getter = PropertyImplementation<TBaseType, TDeclaringType>.GetGetter<TResult>(property.Name);

            var comparer = EqualityComparer<TResult>.Default;

            return (pthis, value) =>
            {//This code executes each time property setter is called.
                if (comparer.Equals(value, getter(pthis))) return;
                //base. call
                setter(pthis, value);
                //Directly accessing Concept's protected method.
                pthis.OnPropertyChanged(eventArgs);
            };
        }
    }
}

It is fully safe for refactoring, uses no reflection after type construction and fast enough.

Kols
  • 3,641
  • 2
  • 34
  • 42
Kelqualyn
  • 489
  • 5
  • 7
  • Why do you need `TDeclaration` type parameter on `PropertyImplementation`? Surely you can find appropriate type to call (not callvirt) the getter/setter from with only `TImplementation`? – Andrew Savinykh Jun 22 '15 at 03:13
  • TImplementation works in most of cases. Exceptions are: 1. Properties redefined with "new" C# keyvord. 2. Properties of explicit interface implementation. – Kelqualyn Jul 29 '15 at 05:53
4

Based on the answer by Thomas which was adapted from an answer by Marc I've turned the reflecting property changed code into a base class:

public abstract class PropertyChangedBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) 
            handler(this, new PropertyChangedEventArgs(propertyName));
    }

    protected void OnPropertyChanged<T>(Expression<Func<T>> selectorExpression)
    {
        if (selectorExpression == null)
            throw new ArgumentNullException("selectorExpression");
        var me = selectorExpression.Body as MemberExpression;

        // Nullable properties can be nested inside of a convert function
        if (me == null)
        {
            var ue = selectorExpression.Body as UnaryExpression;
            if (ue != null)
                me = ue.Operand as MemberExpression;
        }

        if (me == null)
            throw new ArgumentException("The body must be a member expression");

        OnPropertyChanged(me.Member.Name);
    }

    protected void SetField<T>(ref T field, T value, Expression<Func<T>> selectorExpression, params Expression<Func<object>>[] additonal)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return;
        field = value;
        OnPropertyChanged(selectorExpression);
        foreach (var item in additonal)
            OnPropertyChanged(item);
    }
}

Usage is the same as Thomas' answer except that you can pass additional properties to notify for. This was necessary to handle calculated columns which need to be refreshed in a grid.

private int _quantity;
private int _price;

public int Quantity 
{ 
    get { return _quantity; } 
    set { SetField(ref _quantity, value, () => Quantity, () => Total); } 
}
public int Price 
{ 
    get { return _price; } 
    set { SetField(ref _price, value, () => Price, () => Total); } 
}
public int Total { get { return _price * _quantity; } }

I have this driving a collection of items stored in a BindingList exposed via a DataGridView. It has eliminated the need for me to do manual Refresh() calls to the grid.

StuffOfInterest
  • 518
  • 3
  • 11
3

I created an Extension Method in my base Library for reuse:

public static class INotifyPropertyChangedExtensions
{
    public static bool SetPropertyAndNotify<T>(this INotifyPropertyChanged sender,
               PropertyChangedEventHandler handler, ref T field, T value, 
               [CallerMemberName] string propertyName = "",
               EqualityComparer<T> equalityComparer = null)
    {
        bool rtn = false;
        var eqComp = equalityComparer ?? EqualityComparer<T>.Default;
        if (!eqComp.Equals(field,value))
        {
            field = value;
            rtn = true;
            if (handler != null)
            {
                var args = new PropertyChangedEventArgs(propertyName);
                handler(sender, args);
            }
        }
        return rtn;
    }
}

This works with .Net 4.5 because of CallerMemberNameAttribute. If you want to use it with an earlier .Net version you have to change the method declaration from: ...,[CallerMemberName] string propertyName = "", ... to ...,string propertyName, ...

Usage:

public class Dog : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    string _name;

    public string Name
    {
        get { return _name; }
        set
        {
            this.SetPropertyAndNotify(PropertyChanged, ref _name, value);
        }
    }
}
giammin
  • 18,620
  • 8
  • 71
  • 89
3

I keep this around as a snippet. C# 6 adds some nice syntax for invoking the handler.

// INotifyPropertyChanged

public event PropertyChangedEventHandler PropertyChanged;

private void Set<T>(ref T property, T value, [CallerMemberName] string propertyName = null)
{
    if (EqualityComparer<T>.Default.Equals(property, value) == false)
    {
        property = value;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
Mike Ward
  • 3,211
  • 1
  • 29
  • 42
2

If you are using dynamics in .NET 4.5 you don't need to worry about INotifyPropertyChanged.

dynamic obj = new ExpandoObject();
obj.Name = "John";

if Name is bound to some control it just works fine.

Dilshod
  • 3,189
  • 3
  • 36
  • 67
2

Another combined solution is using StackFrame:

public class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void Set<T>(ref T field, T value)
    {
        MethodBase method = new StackFrame(1).GetMethod();
        field = value;
        Raise(method.Name.Substring(4));
    }

    protected void Raise(string propertyName)
    {
        var temp = PropertyChanged;
        if (temp != null)
        {
            temp(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Usage:

public class TempVM : BaseViewModel
{
    private int _intP;
    public int IntP
    {
        get { return _intP; }
        set { Set<int>(ref _intP, value); }
    }
}
Ofir
  • 2,174
  • 1
  • 16
  • 15
2

I resolved in This Way (it's a little bit laboriouse, but it's surely the faster in runtime).

In VB (sorry, but I think it's not hard translate it in C#), I make this substitution with RE:

(?<Attr><(.*ComponentModel\.)Bindable\(True\)>)( |\r\n)*(?<Def>(Public|Private|Friend|Protected) .*Property )(?<Name>[^ ]*) As (?<Type>.*?)[ |\r\n](?![ |\r\n]*Get)

with:

Private _${Name} As ${Type}\r\n${Attr}\r\n${Def}${Name} As ${Type}\r\nGet\r\nReturn _${Name}\r\nEnd Get\r\nSet (Value As ${Type})\r\nIf _${Name} <> Value Then \r\n_${Name} = Value\r\nRaiseEvent PropertyChanged(Me, New ComponentModel.PropertyChangedEventArgs("${Name}"))\r\nEnd If\r\nEnd Set\r\nEnd Property\r\n

This transofrm all code like this:

<Bindable(True)>
Protected Friend Property StartDate As DateTime?

In

Private _StartDate As DateTime?
<Bindable(True)>
Protected Friend Property StartDate As DateTime?
    Get
        Return _StartDate
    End Get
    Set(Value As DateTime?)
        If _StartDate <> Value Then
            _StartDate = Value
            RaiseEvent PropertyChange(Me, New ComponentModel.PropertyChangedEventArgs("StartDate"))
        End If
    End Set
End Property

And If I want to have a more readable code, I can be the opposite just making the following substitution:

Private _(?<Name>.*) As (?<Type>.*)[\r\n ]*(?<Attr><(.*ComponentModel\.)Bindable\(True\)>)[\r\n ]*(?<Def>(Public|Private|Friend|Protected) .*Property )\k<Name> As \k<Type>[\r\n ]*Get[\r\n ]*Return _\k<Name>[\r\n ]*End Get[\r\n ]*Set\(Value As \k<Type>\)[\r\n ]*If _\k<Name> <> Value Then[\r\n ]*_\k<Name> = Value[\r\n ]*RaiseEvent PropertyChanged\(Me, New (.*ComponentModel\.)PropertyChangedEventArgs\("\k<Name>"\)\)[\r\n ]*End If[\r\n ]*End Set[\r\n ]*End Property

With

${Attr} ${Def} ${Name} As ${Type}

I throw to replace the IL code of the set method, but I can't write a lot of compiled code in IL... If a day I write it, I'll say you!

Lucio Menci
  • 133
  • 6
2

Here is a Unity3D or non-CallerMemberName version of NotifyPropertyChanged

public abstract class Bindable : MonoBehaviour, INotifyPropertyChanged
{
    private readonly Dictionary<string, object> _properties = new Dictionary<string, object>();
    private static readonly StackTrace stackTrace = new StackTrace();
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    ///     Resolves a Property's name from a Lambda Expression passed in.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="property"></param>
    /// <returns></returns>
    internal string GetPropertyName<T>(Expression<Func<T>> property)
    {
        var expression = (MemberExpression) property.Body;
        var propertyName = expression.Member.Name;

        Debug.AssertFormat(propertyName != null, "Bindable Property shouldn't be null!");
        return propertyName;
    }

    #region Notification Handlers

    /// <summary>
    ///     Notify's all other objects listening that a value has changed for nominated propertyName
    /// </summary>
    /// <param name="propertyName"></param>
    internal void NotifyOfPropertyChange(string propertyName)
    {
        OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
    }

    /// <summary>
    ///     Notifies subscribers of the property change.
    /// </summary>
    /// <typeparam name="TProperty">The type of the property.</typeparam>
    /// <param name="property">The property expression.</param>
    internal void NotifyOfPropertyChange<TProperty>(Expression<Func<TProperty>> property)
    {
        var propertyName = GetPropertyName(property);
        NotifyOfPropertyChange(propertyName);
    }

    /// <summary>
    ///     Raises the <see cref="PropertyChanged" /> event directly.
    /// </summary>
    /// <param name="e">The <see cref="PropertyChangedEventArgs" /> instance containing the event data.</param>
    internal void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, e);
        }
    }

    #endregion

    #region Getters

    /// <summary>
    ///     Gets the value of a property
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="name"></param>
    /// <returns></returns>
    internal T Get<T>(Expression<Func<T>> property)
    {
        var propertyName = GetPropertyName(property);
        return Get<T>(GetPropertyName(property));
    }

    /// <summary>
    ///     Gets the value of a property automatically based on its caller.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    internal T Get<T>()
    {
        var name = stackTrace.GetFrame(1).GetMethod().Name.Substring(4); // strips the set_ from name;
        return Get<T>(name);
    }

    /// <summary>
    ///     Gets the name of a property based on a string.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="name"></param>
    /// <returns></returns>
    internal T Get<T>(string name)
    {
        object value = null;
        if (_properties.TryGetValue(name, out value))
            return value == null ? default(T) : (T) value;
        return default(T);
    }

    #endregion

    #region Setters

    /// <summary>
    ///     Sets the value of a property whilst automatically looking up its caller name.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    internal void Set<T>(T value)
    {
        var propertyName = stackTrace.GetFrame(1).GetMethod().Name.Substring(4); // strips the set_ from name;
        Set(value, propertyName);
    }

    /// <summary>
    ///     Sets the value of a property
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <param name="name"></param>
    internal void Set<T>(T value, string propertyName)
    {
        Debug.Assert(propertyName != null, "name != null");
        if (Equals(value, Get<T>(propertyName)))
            return;
        _properties[propertyName] = value;
        NotifyOfPropertyChange(propertyName);
    }

    /// <summary>
    ///     Sets the value of a property based off an Expression (()=>FieldName)
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <param name="property"></param>
    internal void Set<T>(T value, Expression<Func<T>> property)
    {
        var propertyName = GetPropertyName(property);

        Debug.Assert(propertyName != null, "name != null");

        if (Equals(value, Get<T>(propertyName)))
            return;
        _properties[propertyName] = value;
        NotifyOfPropertyChange(propertyName);
    }

    #endregion
}

This code enables you to write property backing fields like this:

  public string Text
    {
        get { return Get<string>(); }
        set { Set(value); }
    }

Furthermore, in resharper if you create a pattern/search snippet you can then also automate you're workflow by converting simple prop fields into the above backing.

Search Pattern:

public $type$ $fname$ { get; set; }

Replace Pattern:

public $type$ $fname$
{
    get { return Get<$type$>(); }
    set { Set(value); }
}
Scott
  • 1,978
  • 1
  • 16
  • 36
2

I have written an article that helps with this (https://msdn.microsoft.com/magazine/mt736453). You can use the SolSoft.DataBinding NuGet package. Then you can write code like this:

public class TestViewModel : IRaisePropertyChanged
{
  public TestViewModel()
  {
    this.m_nameProperty = new NotifyProperty<string>(this, nameof(Name), null);
  }

  private readonly NotifyProperty<string> m_nameProperty;
  public string Name
  {
    get
    {
      return m_nameProperty.Value;
    }
    set
    {
      m_nameProperty.SetValue(value);
    }
  }

  // Plus implement IRaisePropertyChanged (or extend BaseViewModel)
}

Benefits:

  1. base class is optional
  2. no reflection on every 'set value'
  3. can have properties that depend on other properties, and they all automatically raise the appropriate events (article has an example of this)
Mark Sowul
  • 10,244
  • 1
  • 45
  • 51
2

I came up with this base class to implement the observable pattern, pretty much does what you need ("automatically" implementing the set and get). I spent line an hour on this as prototype, so it doesn't have many unit tests, but proves the concept. Note it uses the Dictionary<string, ObservablePropertyContext> to remove the need for private fields.

  public class ObservableByTracking<T> : IObservable<T>
  {
    private readonly Dictionary<string, ObservablePropertyContext> _expando;
    private bool _isDirty;

    public ObservableByTracking()
    {
      _expando = new Dictionary<string, ObservablePropertyContext>();

      var properties = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList();
      foreach (var property in properties)
      {
        var valueContext = new ObservablePropertyContext(property.Name, property.PropertyType)
        {
          Value = GetDefault(property.PropertyType)
        };

        _expando[BuildKey(valueContext)] = valueContext;
      }
    }

    protected void SetValue<T>(Expression<Func<T>> expression, T value)
    {
      var keyContext = GetKeyContext(expression);
      var key = BuildKey(keyContext.PropertyName, keyContext.PropertyType);

      if (!_expando.ContainsKey(key))
      {
        throw new Exception($"Object doesn't contain {keyContext.PropertyName} property.");
      }

      var originalValue = (T)_expando[key].Value;
      if (EqualityComparer<T>.Default.Equals(originalValue, value))
      {
        return;
      }

      _expando[key].Value = value;
      _isDirty = true;
    }

    protected T GetValue<T>(Expression<Func<T>> expression)
    {
      var keyContext = GetKeyContext(expression);
      var key = BuildKey(keyContext.PropertyName, keyContext.PropertyType);

      if (!_expando.ContainsKey(key))
      {
        throw new Exception($"Object doesn't contain {keyContext.PropertyName} property.");
      }

      var value = _expando[key].Value;
      return (T)value;
    }

    private KeyContext GetKeyContext<T>(Expression<Func<T>> expression)
    {
      var castedExpression = expression.Body as MemberExpression;
      if (castedExpression == null)
      {
        throw new Exception($"Invalid expression.");
      }

      var parameterName = castedExpression.Member.Name;

      var propertyInfo = castedExpression.Member as PropertyInfo;
      if (propertyInfo == null)
      {
        throw new Exception($"Invalid expression.");
      }

      return new KeyContext {PropertyType = propertyInfo.PropertyType, PropertyName = parameterName};
    }

    private static string BuildKey(ObservablePropertyContext observablePropertyContext)
    {
      return $"{observablePropertyContext.Type.Name}.{observablePropertyContext.Name}";
    }

    private static string BuildKey(string parameterName, Type type)
    {
      return $"{type.Name}.{parameterName}";
    }

    private static object GetDefault(Type type)
    {
      if (type.IsValueType)
      {
        return Activator.CreateInstance(type);
      }
      return null;
    }

    public bool IsDirty()
    {
      return _isDirty;
    }

    public void SetPristine()
    {
      _isDirty = false;
    }

    private class KeyContext
    {
      public string PropertyName { get; set; }
      public Type PropertyType { get; set; }
    }
  }

  public interface IObservable<T>
  {
    bool IsDirty();
    void SetPristine();
  }

Here's the usage

public class ObservableByTrackingTestClass : ObservableByTracking<ObservableByTrackingTestClass>
  {
    public ObservableByTrackingTestClass()
    {
      StringList = new List<string>();
      StringIList = new List<string>();
      NestedCollection = new List<ObservableByTrackingTestClass>();
    }

    public IEnumerable<string> StringList
    {
      get { return GetValue(() => StringList); }
      set { SetValue(() => StringIList, value); }
    }

    public IList<string> StringIList
    {
      get { return GetValue(() => StringIList); }
      set { SetValue(() => StringIList, value); }
    }

    public int IntProperty
    {
      get { return GetValue(() => IntProperty); }
      set { SetValue(() => IntProperty, value); }
    }

    public ObservableByTrackingTestClass NestedChild
    {
      get { return GetValue(() => NestedChild); }
      set { SetValue(() => NestedChild, value); }
    }

    public IList<ObservableByTrackingTestClass> NestedCollection
    {
      get { return GetValue(() => NestedCollection); }
      set { SetValue(() => NestedCollection, value); }
    }

    public string StringProperty
    {
      get { return GetValue(() => StringProperty); }
      set { SetValue(() => StringProperty, value); }
    }
  }
HoBa
  • 3,442
  • 5
  • 26
  • 33
2

I have just found ActiveSharp - Automatic INotifyPropertyChanged, I have yet to use it, but it looks good.

To quote from it's web site...


Send property change notifications without specifying property name as a string.

Instead, write properties like this:

public int Foo
{
    get { return _foo; }
    set { SetValue(ref _foo, value); }  // <-- no property name here
}

Note that there is no need to include the name of the property as a string. ActiveSharp reliably and correctly figures that out for itself. It works based on the fact that your property implementation passes the backing field (_foo) by ref. (ActiveSharp uses that "by ref" call to identify which backing field was passed, and from the field it identifies the property).

Ian Ringrose
  • 51,220
  • 55
  • 213
  • 317
1

Other things you may want to consider when implementing these sorts of properties is the fact that the INotifyPropertyChang *ed *ing both use event argument classes.

If you have a large number of properties that are being set then the number of event argument class instances can be huge, you should consider caching them as they are one of the areas that a string explosion can occur.

Take a look at this implementation and explanation of why it was conceived.

Josh Smiths Blog

Peter
  • 1,776
  • 13
  • 20
1

An idea using reflection:

class ViewModelBase : INotifyPropertyChanged {

    public event PropertyChangedEventHandler PropertyChanged;

    bool Notify<T>(MethodBase mb, ref T oldValue, T newValue) {

        // Get Name of Property
        string name = mb.Name.Substring(4);

        // Detect Change
        bool changed = EqualityComparer<T>.Default.Equals(oldValue, newValue);

        // Return if no change
        if (!changed) return false;

        // Update value
        oldValue = newValue;

        // Raise Event
        if (PropertyChanged != null) {
            PropertyChanged(this, new PropertyChangedEventArgs(name));
        }//if

        // Notify caller of change
        return true;

    }//method

    string name;

    public string Name {
        get { return name; }
        set {
            Notify(MethodInfo.GetCurrentMethod(), ref this.name, value);
        }
    }//method

}//class
Jack
  • 4,684
  • 2
  • 29
  • 22
  • This is pretty cool, I like it more than expression approach. On the downside, should be slower. – nawfal Aug 12 '14 at 08:11
1

Use this

using System;
using System.ComponentModel;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;


public static class ObservableFactory
{
    public static T Create<T>(T target)
    {
        if (!typeof(T).IsInterface)
            throw new ArgumentException("Target should be an interface", "target");

        var proxy = new Observable<T>(target);
        return (T)proxy.GetTransparentProxy();
    }
}

internal class Observable<T> : RealProxy, INotifyPropertyChanged, INotifyPropertyChanging
{
    private readonly T target;

    internal Observable(T target)
        : base(ImplementINotify(typeof(T)))
    {
        this.target = target;
    }

    public override IMessage Invoke(IMessage msg)
    {
        var methodCall = msg as IMethodCallMessage;

        if (methodCall != null)
        {
            return HandleMethodCall(methodCall);
        }

        return null;
    }

    public event PropertyChangingEventHandler PropertyChanging;
    public event PropertyChangedEventHandler PropertyChanged;



    IMessage HandleMethodCall(IMethodCallMessage methodCall)
    {
        var isPropertySetterCall = methodCall.MethodName.StartsWith("set_");
        var propertyName = isPropertySetterCall ? methodCall.MethodName.Substring(4) : null;

        if (isPropertySetterCall)
        {
            OnPropertyChanging(propertyName);
        }

        try
        {
            object methodCalltarget = target;

            if (methodCall.MethodName == "add_PropertyChanged" || methodCall.MethodName == "remove_PropertyChanged"||
                methodCall.MethodName == "add_PropertyChanging" || methodCall.MethodName == "remove_PropertyChanging")
            {
                methodCalltarget = this;
            }

            var result = methodCall.MethodBase.Invoke(methodCalltarget, methodCall.InArgs);

            if (isPropertySetterCall)
            {
                OnPropertyChanged(methodCall.MethodName.Substring(4));
            }

            return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
        }
        catch (TargetInvocationException invocationException)
        {
            var exception = invocationException.InnerException;
            return new ReturnMessage(exception, methodCall);
        }
    }

    protected virtual void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

    protected virtual void OnPropertyChanging(string propertyName)
    {
        var handler = PropertyChanging;
        if (handler != null) handler(this, new PropertyChangingEventArgs(propertyName));
    }

    public static Type ImplementINotify(Type objectType)
    {
        var tempAssemblyName = new AssemblyName(Guid.NewGuid().ToString());

        var dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
            tempAssemblyName, AssemblyBuilderAccess.RunAndCollect);

        var moduleBuilder = dynamicAssembly.DefineDynamicModule(
            tempAssemblyName.Name,
            tempAssemblyName + ".dll");

        var typeBuilder = moduleBuilder.DefineType(
            objectType.FullName, TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract);

        typeBuilder.AddInterfaceImplementation(objectType);
        typeBuilder.AddInterfaceImplementation(typeof(INotifyPropertyChanged));
        typeBuilder.AddInterfaceImplementation(typeof(INotifyPropertyChanging));
        var newType = typeBuilder.CreateType();
        return newType;
    }
}

}

Dude505
  • 1
  • 1
1

I use the following extension method (using C# 6.0) to make the INPC implemenation as easy as possible:

public static bool ChangeProperty<T>(this PropertyChangedEventHandler propertyChanged, ref T field, T value, object sender,
    IEqualityComparer<T> comparer = null, [CallerMemberName] string propertyName = null)
{
    if (comparer == null)
        comparer = EqualityComparer<T>.Default;

    if (comparer.Equals(field, value))
    {
        return false;
    }
    else
    {
        field = value;
        propertyChanged?.Invoke(sender, new PropertyChangedEventArgs(propertyName));
        return true;
    }
}

The INPC implementation boils down to (you can either implement this every time or create a base class):

public class INPCBaseClass: INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected bool changeProperty<T>(ref T field, T value,
        IEqualityComparer<T> comparer = null, [CallerMemberName] string propertyName = null)
    {
        return PropertyChanged.ChangeProperty(ref field, value, this, comparer, propertyName);
    }
}

Then write your properties like this:

private string testProperty;
public string TestProperty
{
    get { return testProperty; }
    set { changeProperty(ref testProperty, value); }
}

NOTE: You can omit the [CallerMemberName] declaration in the extension method, if you want, but I wanted to keep it flexible.

If you have properties without a backing field you can overload changeProperty:

protected bool changeProperty<T>(T property, Action<T> set, T value,
    IEqualityComparer<T> comparer = null, [CallerMemberName] string propertyName = null)
{
    bool ret = changeProperty(ref property, value, comparer, propertyName);
    if (ret)
        set(property);
    return ret;
}

An example use would be:

public string MyTestProperty
{
    get { return base.TestProperty; }
    set { changeProperty(base.TestProperty, (x) => { base.TestProperty = x; }, value); }
}
Tim Pohlmann
  • 4,140
  • 3
  • 32
  • 61
1

I realize this question already has a gazillion answers, but none of them felt quite right for me. My issue is I don't want any performance hits and am willing to put up with a little verbosity for that reason alone. I also don't care too much for auto properties either, which led me to the following solution:

public abstract class AbstractObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected virtual bool SetValue<TKind>(ref TKind Source, TKind NewValue, params string[] Notify)
    {
        //Set value if the new value is different from the old
        if (!Source.Equals(NewValue))
        {
            Source = NewValue;

            //Notify all applicable properties
            foreach (var i in Notify)
                OnPropertyChanged(i);

            return true;
        }

        return false;
    }

    public AbstractObject()
    {
    }
}

In other words, the above solution is convenient if you don't mind doing this:

public class SomeObject : AbstractObject
{
    public string AnotherProperty
    {
        get
        {
            return someProperty ? "Car" : "Plane";
        }
    }

    bool someProperty = false;
    public bool SomeProperty
    {
        get
        {
            return someProperty;
        }
        set
        {
            SetValue(ref someProperty, value, "SomeProperty", "AnotherProperty");
        }
    }

    public SomeObject() : base()
    {
    }
}

Pros

  • No reflection
  • Only notifies if old value != new value
  • Notify multiple properties at once

Cons

  • No auto properties (you can add support for both, though!)
  • Some verbosity
  • Boxing (small performance hit?)

Alas, it is still better than doing this,

set
{
    if (!someProperty.Equals(value))
    {
        someProperty = value;
        OnPropertyChanged("SomeProperty");
        OnPropertyChanged("AnotherProperty");
    }
}

For every single property, which becomes a nightmare with the additional verbosity ;-(

Note, I do not claim this solution is better performance-wise compared to the others, just that it is a viable solution for those who don't like the other solutions presented.

1

I suggest to use ReactiveProperty. This is the shortest method except Fody.

public class Data : INotifyPropertyChanged
{
    // boiler-plate
    ...
    // props
    private string name;
    public string Name
    {
        get { return name; }
        set { SetField(ref name, value, "Name"); }
    }
}

instead

public class Data
{
    // Don't need boiler-plate and INotifyPropertyChanged

    // props
    public ReactiveProperty<string> Name { get; } = new ReactiveProperty<string>();
}

(DOCS)

Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
soi
  • 11
  • 1
1

I'm writing a library that deals with INotifyPropertyChanged, and the main idea is using a dynamic proxy to notify changes.

the repo is here: CaulyKan/NoMorePropertyChanged

with this library, you can write:

    public dynamic Test1Binding { get; set; }
    public TestDTO Test1
    {
        get { return (TestDTO)Test1Binding; }
        set { SetBinding(nameof(Test1Binding), value); }
    }

Then make all bindings and modifications go to Test1Binding, which will notify PropertyChange and CollectionChanged automatically no matter how complex TestDTO is.

it can also handle dependencies.

    [DependsOn("Test1Binding.TestString")]
    public string Test2
    {
        get { return Test1Binding.TestString; }
    }

Please give me some suggestions.

Cauly
  • 370
  • 1
  • 2
  • 12
0

Another Idea...

 public class ViewModelBase : INotifyPropertyChanged
{
    private Dictionary<string, object> _propertyStore = new Dictionary<string, object>();
    protected virtual void SetValue<T>(T value, [CallerMemberName] string propertyName="") {
        _propertyStore[propertyName] = value;
        OnPropertyChanged(propertyName);
    }
    protected virtual T GetValue<T>([CallerMemberName] string propertyName = "")
    {
        object ret;
        if (_propertyStore.TryGetValue(propertyName, out ret))
        {
            return (T)ret;
        }
        else
        {
            return default(T);
        }
    }

    //Usage
    //public string SomeProperty {
    //    get { return GetValue<string>();  }
    //    set { SetValue(value); }
    //}

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        var temp = PropertyChanged;
        if (temp != null)
            temp.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
AechoLiu
  • 17,522
  • 9
  • 100
  • 118
0

=> here my solution with the following features

 public ResourceStatus Status
 {
     get { return _status; }
     set
     {
         _status = value;
         Notify(Npcea.Status,Npcea.Comments);
     }
 }
  1. no refelction
  2. short notation
  3. no magic string in your business code
  4. Reusability of PropertyChangedEventArgs across application
  5. Possibility to notify multiple properties in one statement
Community
  • 1
  • 1
Bruno
  • 1,944
  • 13
  • 22
0

Prism 5 implementation:

public abstract class BindableBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual bool SetProperty<T>(ref T storage,
                                          T value,
                                          [CallerMemberName] string propertyName = null)
    {
        if (object.Equals(storage, value)) return false;

        storage = value;
        this.OnPropertyChanged(propertyName);

        return true;
    }

    protected void OnPropertyChanged(string propertyName)
    {
        var eventHandler = this.PropertyChanged;
        if (eventHandler != null)
        {
            eventHandler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    protected void OnPropertyChanged<T>(Expression<Func<T>> propertyExpression)
    {
        var propertyName = PropertySupport.ExtractPropertyName(propertyExpression);
        this.OnPropertyChanged(propertyName);
    }
}

public static class PropertySupport
{
    public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
    {
        if (propertyExpression == null)
        {
            throw new ArgumentNullException("propertyExpression");
        }

        var memberExpression = propertyExpression.Body as MemberExpression;
        if (memberExpression == null)
        {
            throw new ArgumentException("The expression is not a member access expression.", "propertyExpression");
        }

        var property = memberExpression.Member as PropertyInfo;
        if (property == null)
        {
            throw new ArgumentException("The member access expression does not access a property.", "propertyExpression");
        }

        var getMethod = property.GetMethod;
        if (getMethod.IsStatic)
        {
            throw new ArgumentException("The referenced property is a static property.", "propertyExpression");
        }

        return memberExpression.Member.Name;
    }
}
Jeson Martajaya
  • 6,996
  • 7
  • 54
  • 56
-2

Talk about massive overengineering. This is significantly more complex than just doing it the right way and gives little to no benefit. If your IDE supports code snippets (Visual Studio/MonoDevelop do) then you can make implementing this ridiculously simple. All you'd actually have to type is the type of the property and the property name. The extra three lines of code will be autogenerated.

svick
  • 236,525
  • 50
  • 385
  • 514
Alan
  • 409
  • 3
  • 3
  • In order to stay away from magic strings, you can also use the code from this blog post: http://blog.m.jedynak.pl/2009/02/static-typed-propety-names.html – Brett Veenstra Nov 02 '09 at 17:28
  • 13
    Code snippets are nice when you write the code, but can become a pain in maintenance. – T. Fabre Mar 29 '12 at 12:08
  • 4
    Code snippets do not solve the problem at all. The issue is magic strings not being renamed when refactoring property names. – Dan Bechard May 12 '14 at 13:54