5

I am writing a class that generates WPF bindings for properties based on their accessibility. Here is the key method:

static Binding getBinding(PropertyInfo prop)
{
    var bn = new Binding(prop.Name);
    bn.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
    if (prop.CanRead && prop.CanWrite)
        bn.Mode = BindingMode.TwoWay;
    else if (prop.CanRead)
        bn.Mode = BindingMode.OneWay;
    else if (prop.CanWrite)
        bn.Mode = BindingMode.OneWayToSource;
    return bn;
}

However, this is not working as expected. CanWrite is true when it should be false. For instance, for this property:

abstract class AbstractViewModel {
    public virtual string DisplayName { get; protected set; }
}

class ListViewModel : AbstractViewModel {
    //does not override DisplayName
}

I find that the DisplayName property of a ListViewModel is both CanRead and CanWrite. However, if I call prop.GetAccessors(), only the get_DisplayName() accessor is listed.

What is going on here? What do CanRead and CanWrite indicate, if not the protection level of the property? What would be the correct implementation of my method?

Oliver
  • 11,297
  • 18
  • 71
  • 121
  • well, let's start with the fact that AbstractViewModel is not abstract... Said that, I think you cannot expect a deterministic behavior from an incorrect implementation (virtual without derived implementation). –  May 05 '12 at 11:54
  • I think your real question is: how do I check for accessible getters and setters, right? If so, Jon Skeet answers that here: http://stackoverflow.com/a/302492/44372 – Craig O May 05 '12 at 11:55
  • @JaimieOlivares virtual methods and properties don't have to be overridden. Optionally, you can override them. You are right though, `AbstractViewModel` is actually declared as abstract in my application... I will edit the question. – Oliver May 05 '12 at 11:57

1 Answers1

18

What do CanRead and CanWrite indicate?

If you have a question like that you should first look at the documentation.

CanRead:

If the property does not have a get accessor, it cannot be read.

CanWrite:

If the property does not have a set accessor, it cannot be written to.

So, the properties indicate whether there is a get and set accessor, not what their protection level is. One reason for this is that Reflection doesn't know where are you calling it from, so it doesn't know whether you can actually access the accessors.

What you can do is to find out whether you can access the accessors is to call GetGetMethod() and GetSetMethod(). If the property doesn't have public get/set accessors, they will return null.

svick
  • 236,525
  • 50
  • 385
  • 514
  • I see. You say that Reflection doesn't know where it is being called from, but it manages to work out which accessors are visible from the calling location, so I think this definition of `CanRead` and `CanWrite` is a little strange. Thanks for your answer. – Oliver May 05 '12 at 11:55
  • @Oliver - not really. All `CanWrite` is saying is that there *is* a setter. – ChrisF May 05 '12 at 11:59
  • 1
    @Oliver, if you mean that `GetAcessors()` returns only the accessors that are accessible for you, then that's not true. Again, read the documentation and you will find out that it always returns only public accessors, even if you were able to access more of them. – svick May 05 '12 at 12:00