欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C# IsDefined的问题

程序员文章站 2023-11-25 09:57:10
在.net 4.0(当然也包括4.0以前的版本)下,用反射判断某个方法是否运用了自定义attribute时,可以通过调用methodinfo的isdefined()方法进行...

在.net 4.0(当然也包括4.0以前的版本)下,用反射判断某个方法是否运用了自定义attribute时,可以通过调用methodinfo的isdefined()方法进行确认。当然,isdefined()方法事实上定义在methodinfo的父类memberinfo中,但它仅仅被定义为抽象方法,真正的实现是在methodinfo的子类dynamicmethod中。调用方式如下所示:

复制代码 代码如下:
methodinfo.isdefined(typeof(myattribute), false)

然而,在实际开发中,我发现该方法有一个问题。如果获得methodinfo的方式是通过加载程序集,然后利用反射方式获得的methodinfo对象,即使该方法运用了自定义attribute,返回的结果仍然是false。例如,我们将需要判断的方法所在的类定义到一个单独的project中,并编译为单独的dll文件,然后,利用assembly的loadfile()方式获得程序集:

复制代码 代码如下:
var assembly = assembly.loadfile(assemblypath);
var types = assembly.getexportedtypes();
types.tolist().foreach(
  type =>
  {
      var flag =
          type.getmethods().where(methodinfo => !methodinfo.isabstract).any(
              methodinfo => methodinfo.isdefined(typeof(myattribute), false));
      console.writeline("flag of isdefined is: {0}", flag);
  }
);

打印出来的值为false。

反之,如果不是通过加载程序集,而是直接通过typeof()获得的type,并调用其下methodinfo.isdefined()方法,只要该方法被运用了指定的attribute,返回的结果则为true。

分析原因,大约是获得type的方式不同所造成的。assembly类的getexportedtype()实现如下所示:

复制代码 代码如下:
[securitysafecritical]
public override type[] getexportedtypes()
{
    type[] o = null;
    getexportedtypes(this.getnativehandle(), jithelpers.getobjecthandleonstack<type[]>(ref o));
    return o;
}

注意,这里返回的type[]事实上是通过引用方式传递给了jithelpers的getobjecthandleonstack<type[]>方法中:

复制代码 代码如下:
[targetedpatchingoptout("performance critical to inline across ngen image boundaries"), securitycritical]
internal static objecthandleonstack getobjecthandleonstack<t>(ref t o) where t: class
{
    typedreference reference = __makeref(o);
    return new objecthandleonstack(reference.getpointeronstack());
}

这里将type转换成了typedreference。关键大约就是这里,可惜我无法找到typeof()的具体实现方式。代码追踪到这里,就无法判断这里发生的真实原因了。若要了解.net底层机制的同学,可以告诉我。

若要解决反射方式无法通过isdefined()判断的问题,可以调用methodinfo的getcustomattribute()方法。例如:

复制代码 代码如下:
private static bool isappliedwith(this methodinfo methodinfo, type attributetype, string attributename)
{
    return methodinfo.getcustomattributes(attributetype, false).tostring().contains(attributename);
}

无论是利用反射加载,还是使用typeof,采用这种方式判断方法是否运用了指定的attribute,都是能够生效的。

以上就是c#isdefined的问题的全部内容,希望能给大家一个参考,也希望大家多多支持。