/// <summary>
        /// Lưu thông tin cấu hình trong setting xuống file, dùng khi admn muốn thay đổi cấu hình kết nối CSDL
        /// </summary>
        public virtual void SaveSettings(DataSettings settings, string filePath = null)
        {
            if (settings == null) throw new NullReferenceException("settings");
            filePath = GetPhysicalFilePath(filePath);

            if(!File.Exists(filePath))
                using (File.Create(filePath)) { }

            File.WriteAllText(filePath, ComposeSettings(settings));
        }
        /// <summary>
        /// Chuyển dữ liệu settings thành dạng chuỗi để có thể ghi xuống file
        /// 
        /// Trả về chuỗi kết nối được tạo ra từ thông tin lấy từ settings // xem lại mục đích của hàm, nếu là chuỗi kết nối
        /// thì phải tác ra 1 hàm riêng để tạo chuỗi xuất txt
        /// </summary>
        protected virtual string ComposeSettings(DataSettings settings)
        {
            if (settings == null) return string.Empty;

            string result = string.Format("DataProvider: {0}{2}DataConnectionString: {1}{2}",
                                 settings.DataProvider,
                                 settings.DataConnectionString,
                                 Environment.NewLine
                );
            if (settings.RawDataSettings != null && settings.RawDataSettings.Count > 0) //// khác ở đây
            {
                string str = string.Join("", settings.RawDataSettings.Select(p =>
                    string.Format("{0}: {1}{2}", p.Key, p.Value, Environment.NewLine)));
                result += str;
            }

            return result;
        }
        protected virtual DataSettings ParseSettings(string text)
        {
            var shellSettings = new DataSettings();
            if (string.IsNullOrWhiteSpace(text)) return shellSettings;

            var settings = new List<string>();
            using (var reader = new StringReader(text))
            {
                string str;
                while ((str = reader.ReadLine()) != null)
                    settings.Add(str);
            }

            foreach (var setting in settings)
            {
                var separatorIndex = setting.IndexOf(separator);
                if (separatorIndex == -1)
                {
                    continue;
                }
                string key = setting.Substring(0, separatorIndex).Trim();
                string value = setting.Substring(separatorIndex + 1).Trim();

                switch (key)
                {
                    case "DataProvider":
                        shellSettings.DataProvider = value;
                        break;
                    case "DataConnectionString":
                        shellSettings.DataConnectionString = value;
                        break;
                    default:
                        shellSettings.RawDataSettings.Add(key, value);
                        break;
                }
            }

            return shellSettings;
        }
 // lấy settings qua DI
 public EfDataProviderManager(DataSettings settings)
     : base(settings)
 {
 }
        /// <summary>
        /// Load data settings
        /// </summary>
        /// <param name="filePath">File path; pass null to use the default settings file</param>
        /// <param name="reloadSettings">Whether to reload data, if they already loaded</param>
        /// <param name="fileProvider">File provider</param>
        /// <returns>Data settings</returns>
        public static DataSettings LoadSettings(string filePath = null, bool reloadSettings = false, IResearchFileProvider fileProvider = null)
        {
            if (!reloadSettings && Singleton <DataSettings> .Instance != null)
            {
                return(Singleton <DataSettings> .Instance);
            }

            fileProvider = fileProvider ?? CommonHelper.DefaultFileProvider;
            filePath     = filePath ?? fileProvider.MapPath(ResearchDataSettingsDefaults.FilePath);

            //check whether file exists
            if (!fileProvider.FileExists(filePath))
            {
                //if not, try to parse the file that was used in previous nopCommerce versions
                filePath = fileProvider.MapPath(ResearchDataSettingsDefaults.ObsoleteFilePath);
                if (!fileProvider.FileExists(filePath))
                {
                    return(new DataSettings());
                }

                //get data settings from the old txt file
                var dataSettings = new DataSettings();
                using (var reader = new StringReader(fileProvider.ReadAllText(filePath, Encoding.UTF8)))
                {
                    string settingsLine;
                    while ((settingsLine = reader.ReadLine()) != null)
                    {
                        var separatorIndex = settingsLine.IndexOf(':');
                        if (separatorIndex == -1)
                        {
                            continue;
                        }

                        var key   = settingsLine.Substring(0, separatorIndex).Trim();
                        var value = settingsLine.Substring(separatorIndex + 1).Trim();

                        switch (key)
                        {
                        case "DataProvider":
                            dataSettings.DataProvider = System.Enum.TryParse(value, true, out DataProviderType providerType) ? providerType : DataProviderType.Unknown;
                            continue;

                        case "DataConnectionString":
                            dataSettings.DataConnectionString = value;
                            continue;

                        default:
                            dataSettings.RawDataSettings.Add(key, value);
                            continue;
                        }
                    }
                }

                //save data settings to the new file
                SaveSettings(dataSettings, fileProvider);

                //and delete the old one
                fileProvider.DeleteFile(filePath);

                Singleton <DataSettings> .Instance = dataSettings;
                return(Singleton <DataSettings> .Instance);
            }

            var text = fileProvider.ReadAllText(filePath, Encoding.UTF8);

            if (string.IsNullOrEmpty(text))
            {
                return(new DataSettings());
            }

            //get data settings from the JSON file
            Singleton <DataSettings> .Instance = JsonConvert.DeserializeObject <DataSettings>(text);

            return(Singleton <DataSettings> .Instance);
        }
 protected BaseDataProviderManager(DataSettings settings)
 {
     if (settings == null) throw new ArgumentNullException("settings");
     this.Settings = settings;
 }