private static Dictionary <AddinManagerAssembly, List <IExcelExCommand> > DeserializeAssemblies(
            AssemblyInfos amInfos)
        {
            var nodesInfo = new Dictionary <AddinManagerAssembly, List <IExcelExCommand> >(new AssemblyComparer());

            //
            if (amInfos != null)
            {
                foreach (string assemblyPath in amInfos.AssemblyPaths)
                {
                    if (File.Exists(assemblyPath))
                    {
                        // 将每一个程序集中的外部命令提取出来
                        List <IExcelExCommand> m = ExCommandFinder.RetriveExternalCommandsFromAssembly(assemblyPath);
                        if (m.Any())
                        {
                            Assembly             ass        = m[0].GetType().Assembly;
                            AddinManagerAssembly amAssembly = new AddinManagerAssembly(assemblyPath, ass);
                            nodesInfo.Add(amAssembly, m);
                        }
                    }
                }
            }
            return(nodesInfo);
        }
        /// <summary> 将 Settings 配置文件中的字符进行反序列化 </summary>
        /// <returns></returns>
        /// <remarks>对于Excel.NET的开发,不要在 IExtensionApplication.Initialize() 方法中执行此操作,否则即使在Initialize时可以正常序列化,
        /// 但是在调用ExternalCommand时还是会出bug,通常的报错为:没有为该对象定义无参数的构造函数。 </remarks>
        public static Dictionary <AddinManagerAssembly, List <IExcelExCommand> > GetInfosFromSettings()
        {
            var nodesInfo = new Dictionary <AddinManagerAssembly, List <IExcelExCommand> >(new AssemblyComparer());

            // 提取配置文件中的数据
            AssemblyInfoSettings s = new AssemblyInfoSettings();

            if (!string.IsNullOrEmpty(s.AssemblyInfoSerial))
            {
                // 提取字符
                AssemblyInfos amInfos = StringSerializer.Decode64(s.AssemblyInfoSerial) as AssemblyInfos;

                // 提取数据
                nodesInfo = DeserializeAssemblies(amInfos);
            }

            return(nodesInfo);
        }
        public static void SaveAssemblyInfosToSettings(
            Dictionary <AddinManagerAssembly, List <IExcelExCommand> > nodesInfo)
        {
            // 转换为可序列化的数据
            List <string> assemblyPaths = nodesInfo.Select(r => r.Key.Path).ToList();
            AssemblyInfos amInfos       = new AssemblyInfos()
            {
                AssemblyPaths = assemblyPaths.ToArray()
            };

            // 序列化
            string amInfosString = StringSerializer.Encode64(amInfos);

            // 保存到物理存储中
            AssemblyInfoSettings s = new AssemblyInfoSettings();

            s.AssemblyInfoSerial = amInfosString;
            s.Save();
        }
        /// <summary> 将外部 二进制文件 中的字符进行反序列化 </summary>
        /// <remarks>对于Excel.NET的开发,不要在 IExtensionApplication.Initialize() 方法中执行此操作,否则即使在Initialize时可以正常序列化,
        /// 但是在调用ExternalCommand时还是会出bug,通常的报错为:没有为该对象定义无参数的构造函数。 </remarks>
        public static Dictionary <AddinManagerAssembly, List <IExcelExCommand> > GetInfosFromFile()
        {
            var nodesInfo = new Dictionary <AddinManagerAssembly, List <IExcelExCommand> >(new AssemblyComparer());

            string infoPath = Path.Combine(AddinManagerDirectory, SerializedFileName);

            if (File.Exists(infoPath))
            {
                FileStream    fs    = new FileStream(infoPath, FileMode.Open, FileAccess.Read);
                AssemblyInfos infos = BinarySerializer.DeCode(fs) as AssemblyInfos;

                // 提取数据
                nodesInfo = DeserializeAssemblies(infos);
                //
                fs.Close();
                fs.Dispose();
            }

            return(nodesInfo);
        }
        public static void SaveAssemblyInfosToFile(
            Dictionary <AddinManagerAssembly, List <MethodInfo> > nodesInfo)
        {
            List <string> assemblyPaths = nodesInfo.Select(r => r.Key.Path).ToList();
            AssemblyInfos amInfos       = new AssemblyInfos()
            {
                AssemblyPaths = assemblyPaths.ToArray()
            };

            // 序列化

            string infoPath = Path.Combine(AddinManagerDirectory, SerializedFileName);

            // 保存到物理存储中
            FileStream fs = new FileStream(infoPath, FileMode.Create, FileAccess.Write);

            BinarySerializer.EnCode(fs, amInfos);

            //
            fs.Close();
            fs.Dispose();
        }