C# IsDefined的问题

作者:张逸 时间:2022-07-15 10:37:13 

在.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
0
投稿

猜你喜欢

  • java文件输出流写文件的几种方法

    2023-11-08 16:17:30
  • 详解IntelliJ IDEA 自带的 HTTP Client 接口调用插件吊打 Postman

    2023-08-06 07:56:08
  • 安卓(Android)实现选择时间功能

    2023-11-05 08:20:58
  • java 单例模式和工厂模式实例详解

    2023-04-07 22:10:19
  • Maven中怎么手动添加jar包到本地仓库详解(repository)

    2023-09-08 07:33:20
  • Java中Stream流中map和forEach的区别详解

    2022-07-09 12:24:43
  • Android通过Webservice操作sqlserver数据库实例代码

    2022-12-16 00:46:37
  • SpringBoot整合Shiro两种方式(总结)

    2021-09-08 21:28:24
  • C# JSON格式化转换辅助类 ConvertJson

    2023-09-27 19:40:20
  • Android 听筒模式的具体实现实例

    2023-09-24 03:13:01
  • ehcache模糊批量移除缓存的方法

    2023-01-11 12:30:37
  • IDEA提高开发效率的7个插件(推荐)

    2021-10-16 15:28:35
  • Java获取用户IP属地模拟抖音详解

    2023-04-18 02:01:29
  • Socket结合线程池使用实现客户端和服务端通信demo

    2023-01-21 20:23:50
  • 解决myBatis generator逆向生成没有根据主键的select,update和delete问题

    2022-05-13 06:18:56
  • C#基础之数组排序、对象大小比较实现代码

    2023-05-05 12:36:50
  • Android studio so库找不到问题解决办法

    2023-10-28 02:20:49
  • C#截图程序类似腾讯QQ截图实现代码

    2023-05-07 04:01:01
  • java使用计算md5校验码方式比较两个文件是否相同

    2023-05-10 23:43:16
  • 一篇文章带你入门Java修饰符

    2021-12-25 12:46:01
  • asp之家 软件编程 m.aspxhome.com