public static bool TryGetFunction(
            FieldInfo field,
            Func <string, IntPtr> methodHandleFactory,
            out Delegate @delegate)
        {
            if (field == null)
            {
                throw new ArgumentNullException(nameof(field));
            }

            if (methodHandleFactory == null)
            {
                throw new ArgumentNullException(nameof(methodHandleFactory));
            }

            LoadFunctionAttribute attribute = field.GetCustomAttribute <LoadFunctionAttribute>();

            IntPtr methodHandle = methodHandleFactory.Invoke(attribute.EntryPoint);

            if (methodHandle != IntPtr.Zero)
            {
                @delegate = Marshal.GetDelegateForFunctionPointer(methodHandle, field.FieldType);
                return(true);
            }

            @delegate = null;
            return(false);
        }
        public static bool TryGetFunction(
            FieldInfo field,
            Func <string, IntPtr> methodHandleFactory,
            Expression <Func <object> > onFunctionCall,
            out Delegate @delegate)
        {
            if (field == null)
            {
                throw new ArgumentNullException(nameof(field));
            }

            if (methodHandleFactory == null)
            {
                throw new ArgumentNullException(nameof(methodHandleFactory));
            }

            LoadFunctionAttribute attribute = field.GetCustomAttribute <LoadFunctionAttribute>();

            IntPtr methodHandle = methodHandleFactory.Invoke(attribute.EntryPoint);

            if (methodHandle == IntPtr.Zero && onFunctionCall != null)
            {
                @delegate = field.FieldType.GetEmptyDebugDelegate(onFunctionCall);
                return(false);
            }
            else if (!attribute.DisableOnFunctionCall)
            {
                // TODO:
                //	@delegate = ptr.GetDebugDelegate(field.FieldType, onFunctionCall);
                //	return true;
            }

            @delegate = Marshal.GetDelegateForFunctionPointer(methodHandle, field.FieldType);
            return(true);
        }
        /// <summary>
        /// Loads all unmanaged functions of provided type and binding flags.
        /// </summary>
        /// <param name="type">The type</param>
        /// <param name="methodHandleFactory">The function that retrieves the handle</param>
        /// <returns>returns a collection of error string</returns>
        public static ICollection <string> LoadFunctions(
            this Type type,
            Func <string, IntPtr> methodHandleFactory)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (methodHandleFactory == null)
            {
                throw new ArgumentNullException(nameof(methodHandleFactory));
            }

            var errors = new List <string>();

            IEnumerable <FieldInfo> fields = type
                                             .GetFields(DefaultBindingFlags)
                                             .Where(i => i.IsDefined(typeof(LoadFunctionAttribute)));

            foreach (FieldInfo field in fields)
            {
                if (!UnmanagedHelper.TryGetFunction(field, methodHandleFactory, out Delegate @delegate))
                {
                    LoadFunctionAttribute attribute = field.GetCustomAttribute <LoadFunctionAttribute>();

                    errors.Add($"Failed to load `{type.Name}` function `{attribute.EntryPoint}`.");
                }

                field.SetValue(null, @delegate);
            }

            return(errors);
        }