protected internal Win32Plugin(IntPtr moduleHandle)
        {
            const string PluginNameFuncName        = "Plugin_Name";
            const string PluginDisplayNameFuncName = "Plugin_DisplayName";
            const string PluginVersionFuncName     = "Plugin_Version";
            const string PluginMinVersionFuncName  = "Plugin_MinVersion";
            const string PluginDescriptionFuncName = "Plugin_Description";
            const string PluginGuidFuncName        = "Plugin_Guid";

            Win32Utility.MarshalDelegateFromFunctionPointer(out this.PluginNameFunc, Win32Utility.GetProcAddress, moduleHandle, PluginNameFuncName);
            Win32Utility.MarshalDelegateFromFunctionPointer(out this.PluginDisplayNameFunc, Win32Utility.GetProcAddress, moduleHandle, PluginDisplayNameFuncName);
            Win32Utility.MarshalDelegateFromFunctionPointer(out this.PluginVersionFunc, Win32Utility.GetProcAddress, moduleHandle, PluginVersionFuncName);
            Win32Utility.MarshalDelegateFromFunctionPointer(out this.PluginMinVersionFunc, Win32Utility.GetProcAddress, moduleHandle, PluginMinVersionFuncName);
            Win32Utility.MarshalDelegateFromFunctionPointer(out this.PluginDescriptionFunc, Win32Utility.GetProcAddress, moduleHandle, PluginDescriptionFuncName);
            Win32Utility.MarshalDelegateFromFunctionPointer(out this.PluginGuidFunc, Win32Utility.GetProcAddress, moduleHandle, PluginGuidFuncName);

            const string VersionMajorFuncName    = "Version_Major";
            const string VersionMinorFuncName    = "Version_Minor";
            const string VersionRevisionFuncName = "Version_Revision";
            const string VersionDateFuncName     = "Version_Date";
            const string VersionPeriodFuncName   = "Version_Period";

            Win32Utility.MarshalDelegateFromFunctionPointer(out this.VersionMajorFunc, Win32Utility.GetProcAddress, moduleHandle, VersionMajorFuncName);
            Win32Utility.MarshalDelegateFromFunctionPointer(out this.VersionMinorFunc, Win32Utility.GetProcAddress, moduleHandle, VersionMinorFuncName);
            Win32Utility.MarshalDelegateFromFunctionPointer(out this.VersionRevisionFunc, Win32Utility.GetProcAddress, moduleHandle, VersionRevisionFuncName);
            Win32Utility.MarshalDelegateFromFunctionPointer(out this.VersionDateFunc, Win32Utility.GetProcAddress, moduleHandle, VersionDateFuncName);
            Win32Utility.MarshalDelegateFromFunctionPointer(out this.VersionPeriodFunc, Win32Utility.GetProcAddress, moduleHandle, VersionPeriodFuncName);
        }
        /// <summary>
        /// 将数据从非托管内存块经过指定封送处理到指定类型的托管对象。
        /// </summary>
        /// <typeparam name="T">指定的托管对象的类型。</typeparam>
        /// <param name="ptr">指向非托管内存块的指针。</param>
        /// <param name="marshalFunc">指定封送处理。</param>
        /// <param name="defaultValue">操作前提条件不满足时返回的默认值。此方法的前提条件是 <paramref name="ptr"/> 不为 <see cref="IntPtr.Zero"/> 。</param>
        /// <returns>当 <paramref name="ptr"/> 为 <see cref="IntPtr.Zero"/> 时,返回 <paramref name="defaultValue"/> ;否则返回数据从非托管内存块经过指定封送处理到指定类型的托管对象。</returns>
        /// <exception cref="ArgumentNullException"><paramref name="marshalFunc"/> 的值为 null 。</exception>
        public static T PtrToObjectOrDefault <T>(IntPtr ptr, Func <IntPtr, T> marshalFunc, T defaultValue)
        {
            if (marshalFunc == null)
            {
                throw new ArgumentNullException(nameof(marshalFunc));
            }

            return(Win32Utility.PtrToObjectOrDefault(ptr, (_ptr => _ptr != IntPtr.Zero), marshalFunc, defaultValue));
        }
        /// <summary>
        /// 将导出函数封装到对应委托对象中。
        /// </summary>
        /// <typeparam name="T">对应委托类型。</typeparam>
        /// <param name="func">对应委托对象。</param>
        /// <param name="funcName">导出函数名称。</param>
        /// <param name="funcHandle">Win32Dll中对应导出函数的地址。</param>
        /// <param name="errorMessage">当参数<paramref name="funcHandle"/>指定的导出函数的函数指针封装为托管委托对象失败时抛出的异常的信息。</param>
        /// <exception cref="ArgumentException">
        /// <para>泛型类型<typeparamref name="T"/>不是从<see cref="Delegate"/>基类派生而来的委托类型。</para>
        /// <para>泛型类型<typeparamref name="T"/>是<see cref="Delegate"/>基类自身。</para>
        /// </exception>
        internal static void MarshalDelegateFromFunctionPointer <T>(out T func, string funcName, IntPtr funcHandle, string errorMessage = null) where T : class
        {
            if (!typeof(Delegate).IsAssignableFrom(typeof(T)) || typeof(T).Equals(typeof(Delegate)))
            {
                throw new ArgumentException(string.Format("泛型类型{0}必须为委托类型且不能为{1}", typeof(T).FullName, typeof(Delegate).FullName), nameof(T));
            }

            Win32Utility.MarshalDelegateFromFunctionPointer(out func, funcHandle, errorMessage ?? string.Format("导出函数{0}的函数指针封装为托管委托对象失败。", funcName));
        }
        /// <summary>
        /// 将导出函数封装到对应委托对象中。
        /// </summary>
        /// <typeparam name="T">对应委托类型。</typeparam>
        /// <param name="func">对应委托对象。</param>
        /// <param name="getProcAddressFunc">封装GetProcAddress系统API的委托对象。</param>
        /// <param name="moduleHandle">导出函数所属的DLL模块句柄。</param>
        /// <param name="funcName">导出函数名称。</param>
        /// <param name="errorMessage">当无法获取导出函数地址时抛出的异常的信息。</param>
        /// <exception cref="ArgumentException">
        /// <para>泛型类型<typeparamref name="T"/>不是从<see cref="Delegate"/>基类派生而来的委托类型。</para>
        /// <para>泛型类型<typeparamref name="T"/>是<see cref="Delegate"/>基类自身。</para>
        /// </exception>
        /// <exception cref="Win32Exception">
        /// <para>无法获取参数<paramref name="funcName"/>指定的导出函数的地址。</para>
        /// <param>若指定了参数<paramref name="errorMessage"/>的值且不为<see langword="null"/>,则异常的<see cref="Exception.Message"/>属性值为参数<paramref name="errorMessage"/>的值。否则,为默认值。</param>
        /// </exception>
        public static void MarshalDelegateFromFunctionPointer <T>(out T func, GetProcAddress getProcAddressFunc, IntPtr moduleHandle, string funcName, string errorMessage = null) where T : class
        {
            if (!typeof(Delegate).IsAssignableFrom(typeof(T)) || typeof(T).Equals(typeof(Delegate)))
            {
                throw new ArgumentException(string.Format("泛型类型{0}必须为委托类型且不能为{1}", typeof(T).FullName, typeof(Delegate).FullName), nameof(T));
            }

            IntPtr pFunc = getProcAddressFunc(moduleHandle, funcName);

            if (pFunc == IntPtr.Zero)
            {
                throw new Win32Exception(errorMessage ?? string.Format("无法获取导出函数{0}的地址。", funcName));
            }

            Win32Utility.MarshalDelegateFromFunctionPointer(out func, funcName, pFunc);
        }
        /// <summary>
        /// 加载插件。
        /// </summary>
        /// <param name="pluginFileName">插件所在文件路径。</param>
        /// <returns>指定文件中的所有插件对象的集合。</returns>
        /// <exception cref="ArgumentNullException">
        /// 参数<paramref name="pluginFileName"/>为<see langword="null"/>。
        /// </exception>
        /// <exception cref="FileNotFoundException">
        /// 参数<paramref name="pluginFileName"/>指定的文件路径非法或无效。
        /// </exception>
        public IEnumerable <IPlugin> Load(string pluginFileName)
        {
            if (pluginFileName == null)
            {
                throw new ArgumentNullException(nameof(pluginFileName));
            }
            if (!File.Exists(pluginFileName))
            {
                throw new FileNotFoundException("无法从指定文件中加载插件。", pluginFileName);
            }

            IntPtr hModule = Win32Utility.LoadLibrary(pluginFileName);

            if (hModule == IntPtr.Zero)
            {
                throw new Win32Exception(string.Format("无法加载\"{0}\"。", Path.GetFullPath(pluginFileName)), new Win32Exception(Marshal.GetLastWin32Error()));
            }

            Win32Utility.MarshalDelegateFromFunctionPointer(out DPluginLoad loadPluginFunc, Win32Utility.GetProcAddress, hModule, "LoadPlugin");
            Win32Utility.MarshalDelegateFromFunctionPointer(out DPluginRelease releasePluginFunc, Win32Utility.GetProcAddress, hModule, "ReleasePlugin");

            Win32Utility.MarshalDelegateFromFunctionPointer(out DPluginGetPluginList getPluginListFunc, Win32Utility.GetProcAddress, hModule, "GetPluginList", "无法获取插件列表。");

            int count = getPluginListFunc(out IntPtr guid_array);

            foreach (Guid pluginGuid in PtrToStructureEnumerable <Guid>(guid_array, count))
            {
                if (!this.Plugins.ContainsKey(pluginGuid))
                {
                    IWin32Plugin plugin = new Win32Plugin(hModule)
                    {
                        LoadPlugin    = loadPluginFunc,
                        ReleasePlugin = releasePluginFunc,
                        Guid          = pluginGuid
                    };
                    plugin.Load();
                    Console.WriteLine(plugin.Name);
                    this.Plugins.Add(pluginGuid, plugin);
                    yield return(plugin);
                }
            }
        }