为什么CanRead和CanWrite在C#中对于具有覆盖访问器的属性返回false? [英] Why do CanRead and CanWrite return false in C# for properties with overridden accessors?

查看:34
本文介绍了为什么CanRead和CanWrite在C#中对于具有覆盖访问器的属性返回false?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试从派生属性获取属性访问器或使用CanRead/CanWrite时,出于某些原因,未考虑基本的自动属性.

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

CanRead CanWrite 返回值仅基于派生类型, GetMethod SetMethod 也不返回包含基本类型的方法.

CanRead and CanWrite return values based only on the derived type, also GetMethod and SetMethod don't contain methods from base type.

但是,在编写代码时,可以使用基本类型的访问器(这样我们就可以仅使用派生类型中定义的setter来读取覆盖的自动属性).

However when writing code accessors from base type can be used (so that we can read overridden auto-property with only setter defined in derived type).

以下是将其复制为单元测试编写的代码:

Here is the code to reproduce it written as an unit test:

using System.Reflection;
using NUnit.Framework;

[TestFixture]
public class PropertiesReflectionTests
{
    public class WithAutoProperty
    {
        public virtual object Property { get; set; }
    }

    public class OverridesOnlySetter : WithAutoProperty
    {
        public override object Property
        {
            set => base.Property = value;
        }
    }

    private static readonly PropertyInfo Property = typeof(OverridesOnlySetter).GetProperty(nameof(OverridesOnlySetter.Property));

    // This one is passing
    [Test]
    public void Property_ShouldBeReadable()
    {
        var overridesOnlySetter = new OverridesOnlySetter {Property = "test"};

        Assert.AreEqual(overridesOnlySetter.Property, "test");
    }

    // This one is failing
    [Test]
    public void CanRead_ShouldBeTrue()
    {
        Assert.True(Property.CanRead);
    }

    // And this is failing too
    [Test]
    public void GetMethod_ShouldBeNotNull()
    {
        Assert.NotNull(Property.GetMethod);
    }
}

我希望最后两项测试能够通过,我缺少什么?

I expected last two tests to pass, what am I missing?

推荐答案

我希望最后两项测试能够通过,我缺少什么?

I expected last two tests to pass, what am I missing?

要得到一个明确的答案,您必须问问最初设计.NET及其类型系统的人.那说…

For a definitive answer, you'd have to ask the people who originally designed .NET and its type system. That said…

在我看来,这与提供有关如何编写类型的信息的反射目标是一致的.考虑另一种选择:如果返回的 PropertyInfo 对象包含派生类的setter和基类的getter,该怎么办?从返回的结果中很难理解实际上在哪里声明了什么,并且 PropertyInfo 对象本身可以说是不一致的.这是因为存在 PropertyInfo.DeclaringType 属性,该属性表示该成员的所有信息仅与该声明类型有关.

It seems to me that this is consistent with the goal of reflection providing information about how a type was written. Consider the alternative: what if the PropertyInfo object returned included both the setter from the derived class and the getter from the base class. It would be considerably more difficult to understand from the returned result what was actually declared where, and the PropertyInfo object itself would arguably be inconsistent. This is because there is the PropertyInfo.DeclaringType property which implies that all of the information for the member pertains just to that declaring type.

使用既不是属性也不是事件的成员(它们都封装了类成员的 pair 对),您将获得预期的行为.除非您当然传递了 BindingFlags.DeclaredOnly ,否则它将返回的信息限制为声明类型.但是对于那些类型的成员, DeclaringType 属性明确地告诉您成员实际声明的类型.

With members which are neither properties nor events (both of which encapsulate a pair of class members), you get the behavior you expected. Unless of course you pass BindingFlags.DeclaredOnly, which restricts the returned information to the declaring type. But in the case of those types of members, the DeclaringType property tells you unequivocally in which type the member was actually declared.

带有一个属性, DeclaringType 会告诉您属性在哪个类中声明.然后, SetMethod GetMethod 属性告诉您该类声明了什么.

With a property, the DeclaringType tells you in which class the property was declared. And then the SetMethod and GetMethod properties tell you what that class declared.

恕我直言,这使反射API更简单,更一致且更易于理解.这确实意味着您需要做更多的工作来分析虚拟属性.但是,思考总是要涉及更多的工作".:)

IMHO, this makes the reflection API simpler, more consistent, and easier to understand. It does mean that you have to do a little more work to analyze virtual properties. But then, reflection is always going to involve "a little more work". :)

这篇关于为什么CanRead和CanWrite在C#中对于具有覆盖访问器的属性返回false?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆