網站中的設置實現方式有好幾種,其中有將設置類序列化然後保存到文件中(例如使用XML序列化然後以XML形式保存在文件中),或者將設置信息保存到資料庫中。 保存到資料庫中的方式就是將設置的項作為key,設置的值作為value,以key-value(鍵值對)的形式保存。 下麵使用保存到資料庫中的例子來說明 ...
網站中的設置實現方式有好幾種,其中有將設置類序列化然後保存到文件中(例如使用XML序列化然後以XML形式保存在文件中),或者將設置信息保存到資料庫中。
保存到資料庫中的方式就是將設置的項作為key,設置的值作為value,以key-value(鍵值對)的形式保存。
下麵使用保存到資料庫中的例子來說明,首先是設置信息資料庫表結構:
Name是設置項,Value是設置值。對應的實體類如下:
public class Setting : ISettings
{
public int Id { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
View Code
這裡是使用Entity Framework,下麵是資料庫上下文實體類:
public partial class SettingContext : DbContext
{
public SettingContext():base("name=MyConnection")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer< SettingContext>(null);
modelBuilder.Configurations.Add(new SettingMap());
base.OnModelCreating(modelBuilder);
}
public IQueryable<Setting> Table
{
get
{
return Set<Setting>();
}
}
public IQueryable<Setting> TableNoTracking
{
get
{
return Set<Setting>().AsNoTracking();
}
}
public void Insert(Setting entity)
{
if (entity == null)
{
throw new ArgumentException("entity");
}
Set<Setting>().Add(entity);
SaveChanges();
}
public void Update(Setting entity)
{
if (entity == null)
{
throw new ArgumentException("entity");
}
Set<Setting>().Attach(entity);
Entry(entity).State = EntityState.Modified;
SaveChanges();
}
/// <summary>
/// 載入"設置"
/// </summary>
/// <typeparam name="T">設置必須實現介面ISettings</typeparam>
/// <returns></returns>
public T LoadSetting<T>() where T : ISettings, new()
{
//創建設置實例,然後再對其屬性賦值
var setting = Activator.CreateInstance<T>();
Type t = typeof(T);
//獲取所有的屬性
PropertyInfo[] props = t.GetProperties();
//獲取資料庫中所有的設置
var allSetting = TableNoTracking.ToList();
if (allSetting!= null && allSetting.Count > 0)
{
foreach (PropertyInfo p in props)
{
if (!p.CanRead || !p.CanWrite)
{
continue;
}
string key = t.Name + "." + p.Name;
key = key.Trim().ToLowerInvariant(); //轉換為小寫
var obj = allSetting.Where(s => s.Name == key).FirstOrDefault();
if (obj == null)
{
continue;
}
string valueStr = obj.Value;
//判斷是否可以轉換為
if (!TypeDescriptor.GetConverter(p.PropertyType).CanConvertFrom(typeof(string)))
{
continue;
}
if (!TypeDescriptor.GetConverter(p.PropertyType).IsValid(valueStr))
{
continue;
}
object value = TypeDescriptor.GetConverter(p.PropertyType).ConvertFromInvariantString(valueStr);
p.SetValue(setting, value);
}
}
return setting;
}
/// <summary>
/// 保存設置
/// </summary>
/// <typeparam name="T">設置必須實現介面ISettings</typeparam>
/// <param name="setting"></param>
public void SaveSetting<T>(T setting) where T : ISettings, new()
{
var allProperties = typeof(T).GetProperties();
var allSettings = Table.ToList();
foreach (PropertyInfo prop in allProperties)
{
if (!prop.CanRead || !prop.CanWrite)
{
continue;
}
//判斷是否可以轉換
if (!TypeDescriptor.GetConverter(prop.PropertyType).CanConvertFrom(typeof(string)))
{
continue;
}
string key = typeof(T).Name + "." + prop.Name;
key = key.Trim().ToLowerInvariant();
dynamic value = prop.GetValue(setting, null);
if (value == null)
{
value = "";
}
var obj = allSettings.Where(s => s.Name == key).FirstOrDefault();
//需要轉換為string
string valueStr = TypeDescriptor.GetConverter(prop.PropertyType).ConvertToInvariantString(value);
//已存在設置則更新,不存在則添加
if (obj != null)
{
obj.Value = valueStr;
Update(obj);
}
else
{
obj = new Setting
{
Name = key,
Value = valueStr
};
Insert(obj);
}
}
}
}
View Code
由於需要用到泛型約束,所以要求設置類必須實現介面ISettings
EF映射類:
public class SettingMap : EntityTypeConfiguration<Setting>
{
public SettingMap()
{
this.ToTable("Setting");
this.HasKey(s => s.Id);
this.Property(s => s.Name).HasMaxLength(512);
}
}
View Code
基礎設置類:
/// <summary>
/// 基礎設置
/// </summary>
public class BaseSetting : ISettings
{
[DisplayName("網站名稱")]
public string SiteName { get; set; }
[DisplayName("備案號")]
public string SiteICP { get; set; }
[DisplayName("聯繫方式")]
public string SiteTel { get; set; }
[DisplayName("版權信息")]
public string Copyright { get; set; }
[DisplayName("狀態")]
public bool Status { get; set; }
[DisplayName("緩存時間")]
public int CacheTime { get; set; }
}
View Code
在控制器中如下:
public class SettingController : Controller
{
SettingContext settingContext = new SettingContext();
// GET: Setting
public ActionResult Index()
{
return View();
}
public ActionResult Base()
{
var setting = settingContext.LoadSetting<BaseSetting>();
return View(setting);
}
[HttpPost]
public ActionResult Base(BaseSetting model)
{
if (ModelState.IsValid)
{
settingContext.SaveSetting<BaseSetting>(model);
}
return View(model);
}
}
View Code
視圖代碼(其實使用了Edit視圖基架):
@model SettingDemo.Models.BaseSetting
@{
ViewBag.Title = "Base";
}
<h2>Base</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>BaseSetting</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.SiteName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.SiteName, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.SiteName, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.SiteICP, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.SiteICP, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.SiteICP, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.SiteTel, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.SiteTel, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.SiteTel, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Copyright, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Copyright, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Copyright, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Status, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
@Html.EditorFor(model => model.Status)
@Html.ValidationMessageFor(model => model.Status, "", new { @class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.CacheTime, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.CacheTime, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.CacheTime, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
View Code
瀏覽前臺:
填寫設置,保存,查看資料庫
這裡設置項使用的是類名.屬性名,也可以使用完全名稱(完全命名空間.類名.屬性名),只需適當修改代碼即可。擴展自己的設置類需要類似BaseSetting那樣,實現介面ISettings。
參考資料:nopcommerce商城系統