首先,我一直在网上寻找设计设计模式,但我找不到适用于我的案例的解决方案,或者只能找到像 Use Dependency Injection 这样的神秘答案
问题
我有一个大型ASP .NET解决方案,可以部署到多个生产环境中。代码中的许多决策都是基于Web.config文件中实现的设置(几百个)。目前,他们都是使用NameValueCollection ConfigurationManager.AppSettings访问的。我想在数据库中移动这些设置,以便我可以创建用户界面并在之后更容易地修改它们。
我还希望从Web.config中继续访问这些设置,这样如果数据库出现问题,应用程序就不会中断。
解决方案架构
基本上,解决方案包括以下项目:
守则
Setting类(数据库表几乎相同)。 SettingType是一个枚举,它定义了为UI定义的设置类型:Int,String,Bool和I.
public class Setting
{
/// <summary>
/// Gets or sets the identifier.
/// </summary>
/// <value>
/// The identifier.
/// </value>
public int Id { get; set; }
/// <summary>
/// Gets or sets the name of the setting.
/// </summary>
/// <value>
/// The name of the setting.
/// </value>
public string Name { get; set; }
/// <summary>
/// Gets or sets the type of the setting.
/// </summary>
/// <value>
/// The type of the setting.
/// </value>
public SettingType Type { get; set; }
/// <summary>
/// Gets or sets the setting value.
/// </summary>
/// <value>
/// The setting value.
/// </value>
public object Value { get; set; }
/// <summary>
/// Gets or sets the setting description.
/// </summary>
/// <value>
/// The setting description.
/// </value>
public string Description { get; set; }
/// <summary>
/// Gets or sets the setting key.
/// </summary>
/// <value>
/// The setting key.
/// </value>
public string Key { get; set; }
/// <summary>
/// Gets or sets the default value
/// </summary>
/// <value>
/// The default value
/// </value>
public string Default { get; set; }
}
SettingHelper类(目前完成所有操作,将来会拆分功能):
public static class SettingHelper
{
// Settings collection
private static List<Setting> _settings;
/// <summary>
/// Reloads the settings.
/// </summary>
/// <exception cref="System.Exception"></exception>
public static void LoadSettings()
{
_settings = new List<Setting>();
// Code which loads the settings from the database
}
private static Setting GetSetting(string key)
{
try
{
// if settings are not loaded, we reload them from the database
if (_settings == null || _settings.Count == 0)
LoadSettings();
var value = from Setting setting in _settings
where setting != null && setting.Key == key
select setting;
return value.FirstOrDefault();
}
catch (Exception)
{
return null;
}
}
public static void SetSetting(string key, object newValue, int userID)
{
var currentSetting = GetSetting(key);
if (currentSetting != null && !Convert.ToString(currentSetting.Value).ToUpper().Equals(Convert.ToString(newValue).ToUpper()))
{
// Code which updates the setting value
}
}
// For the UI
public static IEnumerable<Setting> GetAllSettings()
{
if (_settings == null)
LoadSettings();
return _settings;
}
// To change back swiftly to the Web.config in case there are errors in production - will remove in the future
public static bool SettingsFromDataBase
{
get
{
if (HttpContext.Current.Application["SettingsFromDataBase"] == null)
HttpContext.Current.Application["SettingsFromDataBase"] = ConfigurationManager.AppSettings["SettingsFromDataBase"];
bool settingsFromDataBase;
if (bool.TryParse(HttpContext.Current.Application["SettingsFromDataBase"] as string, out settingsFromDataBase))
return settingsFromDataBase;
else return false;
}
}
public static T ObjectToGenericType<T>(object obj)
{
if (obj is T)
{
return (T)obj;
}
else
{
try
{
return (T)Convert.ChangeType(obj, typeof(T));
}
catch (InvalidCastException)
{
return default(T);
}
}
}
public static T GetSetting<T>(string key)
{
if (SettingsFromDataBase)
{
var setting = GetSetting(key);
return setting != null
? ObjectToGenericType<T>(setting.Value)
: ObjectToGenericType<T>(ConfigurationManager.AppSettings[key]);
}
if (HttpContext.Current.Application[key] == null)
HttpContext.Current.Application[key] = ConfigurationManager.AppSettings[key];
return (T)HttpContext.Current.Application[key];
}
// The actual settings which will be used in the other projects
public static string StringSetting
{
get { return GetSetting<string>("StringSetting"); }
}
public static bool BoolSetting
{
get { return GetSetting<bool>("BoolSetting"); }
}
注意:可能使用Reflection对此类进行了改进,但我更愿意避免使用它(除了转换之外)。
问题
目前,SettingHelper位于UI项目中(为了能够从Web.config访问设置)。如何在BLL或集成项目中传输这些设置?
另外,你认为这个实现与静态列表中存储的所有设置是可行的吗?这感觉不太理想。
感谢任何有关改进的帮助或讨论。谢谢。