Why do CanRead and CanWrite return false in C# for properties with overridden accessors?

前端 未结 2 1496
囚心锁ツ
囚心锁ツ 2021-01-18 20:27

When trying to get properties accessors from derived properties or use CanRead / CanWrite, for some reason base auto-properties are not taken into account.

Can

2条回答
  •  庸人自扰
    2021-01-18 20:49

    As Peter Duniho explains in his answer, this seems to require some work.

    It would be easier if PropertyInfo had something like GetBaseDefinition(), but it does not (also this thread), so we have to go through the accessor method. It would also be easier if the method info for the accessor had a reference back to the property info, but it does not, so we run through all properties and assume there is exactly on match.

    So here is a naive solution:

    // does not necessarily work as expected if the property or one of its accessors
    // (getter or setter) is not public
    internal static bool CanReadExt(PropertyInfo pi)
    {
      if (pi.CanRead)
        return true;
    
      // assume we have a setter since we do not have a getter
      var setter = pi.SetMethod
        ?? throw new Exception("Neither getter nor setter in property?");
    
      // try to acquire setter of base property
      var baseSetter = setter.GetBaseDefinition();
    
      // if the property was not overridden, we can return
      if (setter.DeclaringType == baseSetter.DeclaringType)
        return false;
    
      // try to find the base property
      var basePi = baseSetter.DeclaringType.GetProperties()
        .SingleOrDefault(x => x.SetMethod == baseSetter)
        ?? throw new Exception("Set accessor was overridden but we could not find property info for base property.");
    
      // recursively call ourselves
      return CanReadExt(basePi);
    }
    

    It returns true with your PropertiesReflectionTests.Property, so it works in that case. More care would be needed to handle every case, I guess.

    This method can be made an extension method if you prefer.

    A similar method CanWriteExt could be written.

提交回复
热议问题