【问题标题】:How to check if a property is virtual with reflection?如何通过反射检查属性是否是虚拟的?
【发布时间】:2012-08-31 14:52:07
【问题描述】:

给定一个对象,如何判断该对象是否具有虚拟属性?

var entity = repository.GetByID(entityId);

我尝试过查看:

PropertyInfo[] properties = entity.GetType().GetProperties();

但无法辨别是否有任何属性表示虚拟。

【问题讨论】:

    标签: c# reflection virtual


    【解决方案1】:
    PropertyInfo[] properties = entity.GetType().GetProperties()
        .Where(p => p.GetMethod.IsVirtual).ToArray();
    

    或者,对于 .NET 4 及以下版本:

    PropertyInfo[] properties = entity.GetType().GetProperties()
        .Where(p => p.GetGetMethod().IsVirtual).ToArray();
    

    这将获得一个公共虚拟属性列表。

    它不适用于只写属性。如果需要,您可以手动检查CanReadCanWrite,并阅读相应的方法。

    例如:

    PropertyInfo[] properties = entity.GetType().GetProperties()
        .Where(p => (p.CanRead ? p.GetMethod : p.SetMethod).IsVirtual).ToArray();
    

    您也可以只获取第一个访问器:

    PropertyInfo[] properties = entity.GetType().GetProperties()
        .Where(p => p.GetAccessors()[0].IsVirtual).ToArray();
    

    【讨论】:

    • 为了安全地处理私有财产,你可以这样做:(p.CanRead ? p.GetGetMethod(true) : p.GetSetMethod(true)).IsVirtual;
    【解决方案2】:

    仅检查属性访问器的IsVirtual 还将为您提供未在您的类中声明virtual 的接口属性。如果“虚拟属性”是指可以在派生类中覆盖的属性,则还应检查IsFinal(密封):

    var accessor = typeof(MyType).GetProperty("MyProp").GetAccessors()[0];
    var isVirtual = accessor.IsVirtual && ! accessor.IsFinal;
    

    查看此示例应用:

    using System;
    
    namespace VirtualPropertyReflection
    {
        interface I
        {
            int P1 { get; set; }
            int P2 { get; set; }
        }
    
        class A : I
        {
            public int P1 { get; set; }
            public virtual int P2 { get; set; }
    
            static void Main()
            {
                var p1accessor = typeof(A).GetProperty("P1").GetAccessors()[0];
                Console.WriteLine(p1accessor.IsVirtual); // True
                Console.WriteLine(p1accessor.IsFinal); // True
    
                var p2accessor = typeof(A).GetProperty("P2").GetAccessors()[0];
                Console.WriteLine(p2accessor.IsVirtual); // True
                Console.WriteLine(p2accessor.IsFinal); // False
            }
        }
    }
    

    this answer

    【讨论】:

    • 感谢您,很多其他答案都谈到了isVirtual,但合并后的isFinal 检查为我做了。
    【解决方案3】:

    试试

    typeof(YourClass).GetProperty("YouProperty").GetGetMethod().IsVirtual;
    

    【讨论】:

      【解决方案4】:

      使用 GetAccessors 方法,例如第一个属性:

      获取访问器:

      properties[0].GetAccessors()[0].IsVirtual
      

      设置访问器:

      properties[0].GetAccessors()[1].IsVirtual
      

      【讨论】:

        【解决方案5】:

        这有点棘手,因为属性可以是只读的、只写的或读/写的。因此,您需要检查两个底层方法是否是虚拟的,如下所示:

        PropertyInfo pi = ...
        var isVirtual = (pi.CanRead && pi.GetMethod.IsVirtual)
                     || (pi.CanWrite && pi.SetMethod.IsVirtual);
        

        【讨论】:

          【解决方案6】:

          IsVirtual 单独对我不起作用。它告诉我,我所有的非虚拟、不可为空的属性都是虚拟的。我不得不结合使用 IsFinal 和 IsVirtual

          这就是我最终得到的结果:

          PropertyInfo[] nonVirtualProperties = myType.GetProperties().Where(x => x.GetAccessors()[0].IsFinal || !x.GetAccessors()[0].IsVirtual).ToArray();
          
          PropertyInfo[] virtualProperties = myType.GetProperties().Where(x => !x.GetAccessors()[0].IsFinal && x.GetAccessors()[0].IsVirtual).ToArray();
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-11-13
            • 2010-12-06
            • 2015-09-20
            • 2012-07-05
            相关资源
            最近更新 更多