首页 新闻 搜索 专区 学院

【求助】反射属性时,如何判断是否有 Virtual 关键字

0
悬赏园豆:50 [已解决问题] 解决于 2014-10-09 17:23

如代码:

    public class TestClass
    {
        public DateTime Date { get; set; }
        public virtual string Message { get; set; }
    }

反射时如何判断,Message 有 virtual 关键字,而 Date 没有呢?

谢谢。

Srouni的主页 Srouni | 初学一级 | 园豆:9
提问于:2014-10-09 16:14
< >
分享
最佳答案
0

谢谢,诸位,自己解决

Srouni | 初学一级 |园豆:9 | 2014-10-09 17:21

求你对于反射属性时,如何判断是否有 Virtual 关键字

的解决方案。。。

小小高 | 园豆:1037 (小虾三级) | 2016-03-31 10:34
其他回答(3)
0

You could use the IsVirtual property:

var isVirtual = typeof(TestClass).GetMethod("Message").IsVirtual;
 
 
or 
 
var stringType = typeof(string);
var props = stringType.GetProperties();

foreach (var prop in props)
{
  foreach (var accessor in prop.GetAccessors())
  {
    Console.WriteLine("Property {0} accessor {1} declared as virtual {2}", prop.Name, accessor.Name, accessor.IsVirtual);
  }
}

 

收获园豆:16
爱编程的大叔 | 园豆:30753 (高人七级) | 2014-10-09 16:18

GetMethod 不是反射方法时用的么?

如果,用上面的代码,会得到下面异常信息:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.

 

Or 中

是判断属性下的 Set 或 Get 方法,这种方式不准确,如,

 

    public class TestClass : ITC
    {
        public DateTime Date { get; set; }
        public virtual string Message { get; set; }
        public Guid Id { get; set; }
    }

    public interface ITC
    {
        Guid Id { get; set; }
    }

这样 ID 也会被判断为 True 的。

 

支持(0) 反对(0) Srouni | 园豆:9 (初学一级) | 2014-10-09 16:24

@Srouni: 大概是这样的代码,你琢磨琢磨自然就出来了。

既然你还问,我慎重起见,稍微写了一小段代码测试。

这样写是没有问题的。

var myType=typeof(TestClass);
var prop=myType.GetMethod("Message");
console.writeline(prop.isvirtual);

我写了两个方法,一个非virtual, 一个virtual,测试一为FALSE,一为TRUE。

至于刚刚上面写的for each var prop in props,好象props有可能找不到这个方法,没有更多测试,你自己找找反射的相关属性方法及示例代码看看吧。

原则上来说,在这儿提问,你得到isVirtual这个方法,对于一个程序员来说,基本就够了,不能让回答者帮你把所有事情搞定,这样你不会进步的。

支持(0) 反对(0) 爱编程的大叔 | 园豆:30753 (高人七级) | 2014-10-09 16:40

@Srouni: 使用getMethod的话,myType.GetMethod("Id");是空对象。

我不清楚你是已知方法名还是要用遍历的形式,如果是要遍历,应该还有其他方法来分辨是属性还是方法(函数)。

支持(0) 反对(0) 爱编程的大叔 | 园豆:30753 (高人七级) | 2014-10-09 16:43
0

你大叔给你了方案,你也不能照抄啊。你大叔年纪大了,有时难免犯糊涂的。

你把GetMethod修改为GetProperty吧。

此外,你用你大叔的代码后报告的错误很明显,因为Message是Property,用GetMethod自然不能获取到对象,所以会有异常。

在.net里,属性也是方法,不过不能这样获取,属性默认的对应方法名是get_PropertyName和set_PropertyName,所以,把你大叔的代码里里的Message修改为get_Message或set_Message也能解决问题。

使用属性对应的方法时是不安全的(或者不能简单直接使用的),因为属性的get或set可能不同时存在。

收获园豆:17
519740105 | 园豆:5810 (大侠五级) | 2014-10-09 16:42

大叔给答案总是网上乱抄的,不保证正确性,掉进坑里请自埋...

其实主要是大叔年纪大了,眼花了,把属性看成方法了...

不过对于提问来说,好象差别不大,我记得以前上学的时候,数学作业都是抄同学的,顺便还找出他做错的地方。

支持(0) 反对(0) 爱编程的大叔 | 园豆:30753 (高人七级) | 2014-10-09 16:45

@爱编程的大叔:  这种抄法,很牛啊

支持(0) 反对(0) Srouni | 园豆:9 (初学一级) | 2014-10-09 17:03
0

4.0以上的获取:

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

4.0以下的获取:

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

 

 

判断:

var isVirtual = typeof(TestClass).GetProperty("Message").GetGetMethod().IsVirtual;  

 

收获园豆:17
悟行 | 园豆:12422 (专家六级) | 2014-10-09 16:46

我刚开始也是复制到这GetGetMethod,以为是网上的代码写错多写了一个Get,没想到微软居然能写出如此名称的函数来。

楼上说了,如果万一属性是WriteOnly的话,这句会报错的。

支持(0) 反对(0) 爱编程的大叔 | 园豆:30753 (高人七级) | 2014-10-09 16:55

这个不准确 会把 上面代码中的 ID 判断为 Virtual 。

支持(0) 反对(0) Srouni | 园豆:9 (初学一级) | 2014-10-09 16:56

@Srouni: 试试这个:

typeof(Cat).GetProperty("Message").GetAccessors()[0].IsVirtual

public static bool? IsVirtual(this PropertyInfo self)
{
    if (self == null)
        throw new ArgumentNullException("self");

    bool? found = null;

    foreach (MethodInfo method in self.GetAccessors()) {
        if (found.HasValue) {
            if (found.Value != method.IsVirtual)
                return null;
        } else {
            found = method.IsVirtual;
        }
    }

    return found;
}
支持(0) 反对(0) 悟行 | 园豆:12422 (专家六级) | 2014-10-09 17:03

@Srouni: 

  Private Shared Sub Test()
        Dim myType As Type = GetType(TestClass)

        Dim props = myType.GetProperties


        For Each prop In props
            MessageBox.Show(prop.Name & "--" & prop.GetGetMethod.IsVirtual)
        Next
    End Sub

    Public Class TestClass
        Public Property id As String

        Public Property message() As String
            
        Public Overridable Property myMethod() As String
    End Class

Result is:

id -- false

message -- false

myMethod -- true

 

VB.NET里面Overridable对应C#的Virtual

实测没有问题。

支持(0) 反对(0) 爱编程的大叔 | 园豆:30753 (高人七级) | 2014-10-09 17:07

@Srouni: 

 Private Shared Sub Test()
        Dim myType As Type = GetType(TestClass)

        Dim props = myType.GetProperties


        For Each prop In props
            MessageBox.Show(prop.Name & "--" & prop.GetGetMethod.IsVirtual & "--" & prop.GetGetMethod.IsFinal)
        Next
    End Sub

    Public Class TestClass
        Implements ITest
        Public Property id As Guid Implements ITest.id

        Public Property message() As String

        Public Overridable Property myMethod() As String

    End Class

    Public Interface ITest
        Property id As Guid
    End Interface

Modify code to support Interface property.

It will done.

 

Result is:

id -- true -- true

message -- false -- false

myMethod -- true -- false

支持(0) 反对(0) 爱编程的大叔 | 园豆:30753 (高人七级) | 2014-10-09 17:18
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册