Problems with C IsDefined

  • 2021-10-15 11:12:34
  • OfStack

Under. NET 4.0 (and, of course, prior to 4.0), when you use reflection to determine whether a method uses a custom Attribute, you can confirm it by calling the IsDefined () method of MethodInfo. Of course, the IsDefined () method is actually defined in MemberInfo, the parent class of MethodInfo, but it is only defined as an abstract method, and the real implementation is in DynamicMethod, a subclass of MethodInfo. The invocation mode is as follows:

methodInfo.IsDefined(typeof(MyAttribute), false)

However, in actual development, I found that this method has one problem. If the MethodInfo is obtained by loading the assembly and then using the reflective MethodInfo object, even if the method uses a custom Attribute, the result returned is still false. For example, we define the class of the method we need to determine into a separate Project, compile it into a separate dll file, and then use LoadFile () of Assembly to get the assembly:

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);
  }
);

The printed value is false.

On the other hand, if Type is obtained directly through typeof () instead of loading the assembly, and the MethodInfo. IsDefined () method under it is called, the result returned is true as long as the method is applied with the specified Attribute.

Analyzing the reasons, it is probably caused by different ways to obtain Type. The GetExportedType () implementation of the Assembly class looks like this:

[SecuritySafeCritical]
public override Type[] GetExportedTypes()
{
    Type[] o = null;
    GetExportedTypes(this.GetNativeHandle(), JitHelpers.GetObjectHandleOnStack<Type[]>(ref o));
    return o;
}

Note that the Type [] returned here is actually an GetObjectHandleOnStack passed to JitHelpers by reference < Type[] > Method:

[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());
}

Here, Type is converted into TypedReference. This is about the point, but unfortunately I can't find a concrete implementation of typeof (). When the code traces here, it is impossible to judge the real cause of what happened here. If you want to know the underlying mechanism of. NET, you can tell me.

To solve the problem that the reflection mode cannot be determined by IsDefined (), you can call the GetCustomAttribute () method of MethodInfo. For example:

private static bool IsAppliedWith(this MethodInfo methodInfo, Type attributeType, string attributeName) 
{
    return methodInfo.GetCustomAttributes(attributeType, false).ToString().Contains(attributeName);
}

Whether using reflection loading or using typeof, it is effective to judge whether the method uses the specified Attribute in this way.


Related articles: