Load备份方法
public class BaseSettings
{
private Dictionary<string, int> intValues = null;
private Dictionary<string, string> strValues = null;
private Dictionary<string, bool> boolValues = null;
private Dictionary<string, double> doubleValues = null;
private DataSet ds = null;
public static bool TipEnable = true;
private const string intTableName = "IntTable";
private const string stringTableName = "StringTable";
private const string boolTableName = "BoolTable";
private const string doubleTableName = "DoubleTable";
private const string firstFieldName = "ParaName";
private const string secondFieldName = "ParaValue";
public string Name { get; private set; }
//SettingFileName is a file whose extension is .xml
private string SettingFileName
{
get
{
string asmFile = this.GetType().Assembly.Location;
string asmPath = Path.GetDirectoryName(asmFile);
if (string.Compare(Name, "Settings") == 0)
{
return Path.ChangeExtension(asmFile, ".xml");
}
else
{
return Path.Combine(asmPath, string.Format("{0}.xml", Name));
}
}
}
public BaseSettings(string settingName)
{
intValues = new Dictionary<string, int>();
strValues = new Dictionary<string, string>();
boolValues = new Dictionary<string, bool>();
doubleValues = new Dictionary<string, double>();
Name = settingName;
SetupDataset();
//因为我下方写了一个load的虚方法,这里执行this.load意为子类会重写一个load的方法
this.Load();
}
//build up a DataSet ——— the introduction of DataSet are below the code
//build up four DataTable,which are int,double,bool,string
private void SetupDataset()
{
ds = new DataSet(Name);
DataTable tbInt = new DataTable(intTableName);
tbInt.Columns.Add(new DataColumn(firstFieldName, typeof(string)));
tbInt.Columns.Add(new DataColumn(secondFieldName, typeof(int)));
ds.Tables.Add(tbInt);
DataTable tbString = new DataTable(stringTableName);
tbString.Columns.Add(new DataColumn(firstFieldName, typeof(string)));
tbString.Columns.Add(new DataColumn(secondFieldName, typeof(string)));
ds.Tables.Add(tbString);
DataTable tbBool = new DataTable(boolTableName);
tbBool.Columns.Add(new DataColumn(firstFieldName, typeof(string)));
tbBool.Columns.Add(new DataColumn(secondFieldName, typeof(bool)));
ds.Tables.Add(tbBool);
DataTable tbDouble = new DataTable(doubleTableName);
tbDouble.Columns.Add(new DataColumn(firstFieldName, typeof(string)));
tbDouble.Columns.Add(new DataColumn(secondFieldName, typeof(double)));
ds.Tables.Add(tbDouble);
// Set primary key for each table
foreach (DataTable tb in ds.Tables)
{
DataColumn col = tb.Columns[0];
tb.PrimaryKey = new DataColumn[] { col };
tb.Columns[1].AllowDBNull = false;
}
}
public virtual bool Load()
{
return Load(SettingFileName);
}
public virtual bool Load(string filePath)
{
string gZipFile = Path.ChangeExtension(filePath, ".setting");
if (File.Exists(gZipFile))
{
MemoryStream ms = new MemoryStream();
try
{
FileStream fs = File.OpenRead(gZipFile);
DecompressStream(fs, ms);
fs.Dispose();
fs.Close();
}
catch (Exception ex)
{
SetupDataset();
Log(ex);
return false;
}
DataSet dsTmp = new DataSet();
try
{
ms.Position = 0;
dsTmp.ReadXml(ms, XmlReadMode.ReadSchema);
}
catch (Exception ex)
{
SetupDataset();
Log(ex);
return false;
}
//合并两个dataSet
ds.Merge(dsTmp);
UpdateFromDatabase();
return SettingsToProperties(this, this);
}
if (File.Exists(filePath))
{
DataSet dsTmp = new DataSet();
try
{
dsTmp.ReadXml(filePath, XmlReadMode.ReadSchema);
}
catch (Exception ex)
{
SetupDataset();
Log(ex);
return false;
}
//合并两个dataSet
ds.Merge(dsTmp);
UpdateFromDatabase();
return SettingsToProperties(this, this);
}
return false;
}
//write the contents of src to dst
private void DecompressStream(Stream src, Stream dst)
{
byte[] buffer = new byte[4096];
using (GZipStream input = new GZipStream(src, CompressionMode.Decompress, true))
{
int readBytes = 0;
while ((readBytes = input.Read(buffer, 0, buffer.Length)) > 0)
{
dst.Write(buffer, 0, readBytes);
}
}
}
//作用: 将dataSet里的数据同步到4个Dictionary里
public void UpdateFromDatabase()
{
DataTable tb = null;
tb = ds.Tables[intTableName];
foreach (DataRow row in tb.Rows)
{
string Name = row[0] as string;
if (string.IsNullOrEmpty(Name)) continue;
int Value = (int)row[1];
if (!intValues.ContainsKey(Name)) intValues.Add(Name, Value);
else intValues[Name] = Value;
}
tb = ds.Tables[stringTableName];
foreach (DataRow row in tb.Rows)
{
string Name = row[0] as string;
if (string.IsNullOrEmpty(Name)) continue;
string Value = row[1] as string;
if (!strValues.ContainsKey(Name)) strValues.Add(Name, Value);
else strValues[Name] = Value;
}
tb = ds.Tables[boolTableName];
foreach (DataRow row in tb.Rows)
{
string Name = row[0] as string;
if (string.IsNullOrEmpty(Name)) continue;
bool Value = (bool)row[1];
if (!boolValues.ContainsKey(Name)) boolValues.Add(Name, Value);
else boolValues[Name] = Value;
}
tb = ds.Tables[doubleTableName];
foreach (DataRow row in tb.Rows)
{
string Name = row[0] as string;
if (string.IsNullOrEmpty(Name)) continue;
double Value = (double)row[1];
if (!doubleValues.ContainsKey(Name)) doubleValues.Add(Name, Value);
else doubleValues[Name] = Value;
}
}
//将参数读到属性中
public static bool SettingsToProperties(BaseSettings settings, object obj)
{
int res = 1;
Parallel.ForEach<PropertyInfo>(GetConfigProperties(obj), pi =>
{
if (!SettingToProperty(settings, string.Empty, obj, pi))
{
if (res == 1) Interlocked.Exchange(ref res, 0);
}
});
return res == 1;
}
//获取obj里面的所有特性属性
public static List<PropertyInfo> GetConfigProperties(object obj)
{
List<PropertyInfo> pis = new List<PropertyInfo>();
Type tp = typeof(Config);
foreach (PropertyInfo pi in obj.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance))
{
if (pi.IsDefined(tp, true))
{
pis.Add(pi);
}
}
foreach (PropertyInfo pi in obj.GetType().GetProperties())
{
if (pi.IsDefined(tp, true))
{
pis.Add(pi);
}
}
return pis;
}
//将pi这个属性的值在setting中的值更新到pi中
public static bool SettingToProperty(BaseSettings settings, string parentName, object obj, PropertyInfo pi)
{
if (settings == null) return false;
if (!pi.CanWrite) return false;
string name = string.Format("{0}{1}", parentName, pi.Name);
if (pi.PropertyType == typeof(int))
{
int? val = settings.GetIntValue(name);
if (val.HasValue)
{
pi.SetValue(obj, val.Value, null);
return true;
}
}
else if (pi.PropertyType == typeof(double))
{
double? val = settings.GetDoubleValue(name);
if (val.HasValue)
{
pi.SetValue(obj, val.Value, null);
return true;
}
}
else if (pi.PropertyType == typeof(string))
{
string val = settings.GetStringValue(name);
if (!string.IsNullOrEmpty(val))
{
pi.SetValue(obj, val, null);
return true;
}
}
else if (pi.PropertyType == typeof(bool))
{
bool? val = settings.GetBoolValue(name);
if (val.HasValue)
{
pi.SetValue(obj, val.Value, null);
return true;
}
}
return false;
}
//在对应列表中找paraName的
public int? GetIntValue(string paraName)
{
if (intValues.ContainsKey(paraName)) return intValues[paraName];
else return null;
}
public double? GetDoubleValue(string paraName)
{
if (doubleValues.ContainsKey(paraName)) return doubleValues[paraName];
else return null;
}
public string GetStringValue(string paraName)
{
if (strValues.ContainsKey(paraName)) return strValues[paraName];
else return null;
}
public bool? GetBoolValue(string paraName)
{
if (boolValues.ContainsKey(paraName)) return boolValues[paraName];
else return null;
}
}
DataSet类是ADO.NET中最核心的成员之一(ADO.NET是.Net Framework SDK中用以操作数据库的总称)。DataSet可以看作是一个数据容器,从数据库总抽取的数据可以存放在DataSet里面,也就相当与一个缓存区。
各种.net开发平台开发语言开发数据库应用程序,一般都不会直接对数据库进行操作,而是先完成
数据连接
和
通过数据适配器填充DataSet的对象
,然后客户端在通过读取DataSet来获取数据;相反也是一样,若是更新数据,是先对DataSet进行更新,最后同步DataSet和数据库。
DataSet有三大特性:
- 独立性
- 离线性
- DataSet对象可用XML表示的数据视图(是一种关系视图)
DataSet结构:
DataSet——DataTable——row colunm
Load过程解析
-
创建4个字典,用于存放4个不同类型的数据:intValues、strValues、boolValues、doubleValues
-
通过属性获取SettingFileName:返回的是一个该文件目录下的.xml文件
-
创建DataSet作为数据传送的中间缓存区,DataSet里创建了4个dataTable
-
开始读取xml配置文件内容:
文件形式可能有两种 1、以.setting为后缀名的配置文件 2、以.xml为后缀名的配置文件。
如果是setting文件就需要比.xml多一个解压步骤,就是利用GZipStream流将内容写入到MemoryStream流中。再利用DataSet.readxml()来将MemoryStream中的内容读取到DataSet中。 -
将DataSet中的数据同步到4个字典里
遍历所有dataTable里的所有内容,将其赋值到字典里,假若字典里没有的,便添加键值对 -
通过反射获取属性,在将数据传入其中
首先需要通过obj.GetType()获取obj里面的所有属性,返回list<PropertyInfo>
再遍历获取到的属性类型,在对应的dataTable里找到其对应的值
最后用.SetValue方法来设定方法的值