【问题标题】:Get read/write properties of Anonymous Type获取匿名类型的读/写属性
【发布时间】:2009-10-18 17:09:54
【问题描述】:

我需要获取可以写入的匿名类型的所有属性。

例如:

 var person = new {Name = "Person's Name", Age = 25};
 Type anonymousType = person.GetType();
 var properties = anonymousType.GetProperties(BindingFlags.Public | BindingFlags.Instance);

问题是所有属性都有其CanWrite 属性false。这对于非匿名类型返回 true。
我也试过打电话给PropertyInfo.GetSetMethod(),它返回null
如何检查属性是否可以写入?

编辑: 也许知道一个类型是否是匿名的就足够了。如何使用反射确定一个类型是否是匿名的?

【问题讨论】:

    标签: c# reflection anonymous-types


    【解决方案1】:

    从 C# 生成的匿名类型始终不可变,因此可写属性集为空。在 VB 中它是可选的:每个属性 默认 是可变的,但如果你在它前面加上 Key 它是不可变的;只有使用 Key 声明的属性才会计算相等性和哈希码生成。我个人更喜欢 C# 的方法。

    对于非匿名类型的属性,

    CanWrite 并不总是返回 true - 仅适用于可写属性。属性可以是只读的、只写的或读写的。例如:

    public class Test
    {
        // CanWrite will return false. CanRead will return true.
        public int ReadOnly { get { return 10; } }
    
        // CanWrite will return true. CanRead will return false.
        public int WriteOnly { set {} }
    
        // CanWrite will return true. CanRead will return true.
        public int ReadWrite { get { return 10; } set {} }
    }
    

    【讨论】:

    • 嗨,“不总是”?你能否详细说明一下。我也期望生成一个 set 方法。编译器是否足够聪明,仅在使用时才生成设置器? - 谢谢。
    • 也可以通过反射知道一个类型是否是匿名的吗?
    • 不能使用由 C# 生成的匿名类型的 setter - 正如我所说,它始终是不可变的。对于命名类型,是否有 setter 取决于声明,如示例所示。至于检测一个类型是否是由编译器创建的,还有一个关于某个地方的 SO question。我会设法找到它。
    【解决方案2】:

    由于 .NET 2.0 运行时不支持匿名类型,因此没有可靠的方法来确定类型是否为匿名类型。依赖“编译器生成的名称”的格式不是一个安全的修复方法,因为这可能会随着编译器的不同版本而改变。

    听起来您用上面的语句回答了您自己关于“我如何检查是否可以写入属性”的问题:CanWrite 为 false 并且 GetSetMethod(true) 返回 null。这是你不能写信给物业的两个迹象。

    由于我们使用的是 .NET 2.0 运行时,因此 System.Type 上没有“IsAnonymous”属性,因此您实际上没有任何可靠的方法来识别匿名类型。

    【讨论】:

      【解决方案3】:

      无法分配匿名类型的属性,因此反射报告正确。

      如果您查看编译后的 IL,您会注意到尽管 C# 代码看起来使用了普通的初始化程序,但编译器将其重写为构造函数调用,从而允许属性为非- 可在课堂外写。

      【讨论】:

        【解决方案4】:

        如何使用反射确定一个类型是否是匿名的?

        我认为你可以检查该类型是否具有CompilerGenerated 属性

        【讨论】:

          【解决方案5】:

          如何使用反射确定一个类型是否是匿名的?

          只需使用此代码。

          var isAnonymousType = Attribute.IsDefined(dataType, typeof (CompilerGeneratedAttribute), false) && dataType.IsGenericType && dataType.FullName.Contains("Anonymous") &&  (dataType.Attributes & TypeAttributes.NotPublic) == TypeAttributes.NotPublic;
          

          【讨论】:

          • answer 建议您只需检查CompilerGeneratedAttribute。所有这些其他检查真的有必要吗?编辑:看起来您从与 answer 相同的来源获得信息?
          猜你喜欢
          • 2023-03-15
          • 1970-01-01
          • 2010-10-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多