如何检查属性是否为虚拟反射对象?

问题描述 投票:21回答:6

给出一个对象,我如何分辨该对象是否具有虚拟属性?

var entity = repository.GetByID(entityId);

我尝试查看:

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

但是无法确定是否有任何属性表示虚拟。

c# reflection virtual
6个回答
36
投票
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();

15
投票

仅检查属性访问器的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


8
投票

尝试使用

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

5
投票

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

获取访问者:

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

设置访问者:

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

3
投票

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

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

0
投票

单独使用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();
© www.soinside.com 2019 - 2024. All rights reserved.