Search code examples
c#system.reflectionmethodinfo

How do you get DllImportAttribute using System.Reflection?


How do you get info about a DllImport attribute?

I'm using monodevelop inspector to inspect a c# dll that wraps native dll

using System.Runtime.InteropServices;
namespace MonoMac.foo
{
 public class fooFramework
 {
  [DllImport ("/System/Library/Frameworks/foo")]
  public static extern void NSfoo ();
 }
}

I try to "replicate" the inspector functionality in my code using System.Reflection. I got no problem to get a MethodInfo on the NSfoo method. How do you get those (noncustom) attributes? I think

mymethodInfo.Attributes & MethodAttributes.PinvokeImpl

will tell me if the method consists in a extern call. But how can I get more information such as the path to the native dll?

EDIT:
I was using Attribute.GetCustomAttributes(mymethodInfo) or mymethodInfo.GetCustomAttributes(). For some reason, the returned list does not contain any attribute of type DllImport.

Asking explicitly for a DllImportAttribute is the way to go : var dllImport =(DllImportAttribute)mymethodInfo.GetCustomAttribute(typeof(DllImportAttribute)).
If attribute is not null, the "path" is in the property named Value.


Solution

  • Since extern is always static you need to find all static methods and filter them by result of GetCustomAttribute() method:

    public class fooFramework
    {
        [DllImport ("/System/Library/Frameworks/foo")]
        public static extern void NSfoo ();
    }
    ...
    public class MethodData
    {
        public MethodInfo MethodInfo { get; set; }
    
        public DllImportAttribute Attribute { get; set; }
    
        public string DllPath => Attribute.Value;
    }
    ...
    public static List<MethodData> GetDllImportMethods(Type classType)
    {
        var methods = classType.GetMethods(BindingFlags.Public | BindingFlags.Static);
        var result = new List<MethodData>();
        foreach (var methodInfo in methods)
        {
            var dllImportAttribute =
                methodInfo.GetCustomAttribute(typeof(DllImportAttribute));
            if (dllImportAttribute == null)
                continue;
            result.Add(new MethodData()
            {
                MethodInfo = methodInfo,
                Attribute = (DllImportAttribute)dllImportAttribute
            });
        }
    
        return result;
    }
    ...
    //Usage:
    var methods = GetDllImportMethods(typeof(fooFramework));
    Console.WriteLine(methods[0].DllPath); // /System/Library/Frameworks/foo