实现一个最简单最基本的缓存系统。
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Collections;
using System.Text;
using System.Threading;
using System.Collections.Generic;
using System.Reflection;
namespace ConsoleApplication1
{
public class MyCache<T> where T : new()
{
//缓存的数据
private List<T> data;
private void SetData(List<T> data)
{
this.data = data;
}
public List<T> GetData()
{
return this.data;
}
//缓存过期时间
public int timeoutSecond;
//缓存读取数据库的SQL
public string sql;
/// <summary>
/// 启动缓存
/// </summary>
public void StartCache()
{
Console.WriteLine("缓存启动,开始初始化缓存数据...");
DataTable dt = GetDataFromDB(this.sql);
SetData(ConvertHelper<T>.ConvertToList(dt));
Console.WriteLine("缓存启动,初始化数据完成.");
//定时更新缓存
TimerCallback tcb = new TimerCallback(UpdateCache);
Timer tmr = new Timer(tcb, null, timeoutSecond, timeoutSecond);
}
/// <summary>
/// 根据配置的SQL从数据库取得数据
/// </summary>
/// <param name="sql"></param>
/// <returns></returns>
private DataTable GetDataFromDB(string sql)
{
//TODO:根据SQL从数据库取得数据
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("ID", typeof(Int32)));
dt.Columns.Add(new DataColumn("UserName", typeof(String)));
DataRow dr;
int n = new Random().Next(6);
for (int i = 0; i < n; i++)
{
dr = dt.NewRow();
dr[0] = i;
dr[1] = "第" + i.ToString() + "个记录的内容";
dt.Rows.Add(dr);
}
return dt;
}
/// <summary>
/// 更新缓存
/// </summary>
/// <param name="data"></param>
private void UpdateCache(object data)
{
DataTable dt = GetDataFromDB(this.sql);
List<T> newList= ConvertHelper<T>.ConvertToList(dt);
SetData(newList);
Console.WriteLine();
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("缓存更新完成...");
foreach (T t in newList)
{
Console.WriteLine(t.ToString());
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Reflection;
namespace ConsoleApplication1
{
/// <summary>
/// DataTable转换为List的辅助类
/// </summary>
/// <typeparam name="T"></typeparam>
public class ConvertHelper<T> where T : new()
{
/// <summary>
/// 利用反射和泛型
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
public static List<T> ConvertToList(DataTable dt)
{
// 定义集合
List<T> ts = new List<T>();
// 获得此模型的类型
Type type = typeof(T);
//定义一个临时变量
string tempName = string.Empty;
//遍历DataTable中所有的数据行
foreach (DataRow dr in dt.Rows)
{
T t = new T();
// 获得此模型的公共属性
PropertyInfo[] propertys = t.GetType().GetProperties();
//遍历该对象的所有属性
foreach (PropertyInfo pi in propertys)
{
tempName = pi.Name;//将属性名称赋值给临时变量
//检查DataTable是否包含此列(列名==对象的属性名)
if (dt.Columns.Contains(tempName))
{
// 判断此属性是否有Setter
if (!pi.CanWrite) continue;//该属性不可写,直接跳出
//取值
object value = dr[tempName];
//如果非空,则赋给对象的属性
if (value != DBNull.Value)
pi.SetValue(t, value, null);
}
}
//对象添加到泛型集合中
ts.Add(t);
}
return ts;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class UserInfo
{
public int ID { get; set; }
public string UserName { get; set; }
public override string ToString()
{
return "ID:" + this.ID + ",UserName:" + this.UserName;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading;
namespace ConsoleApplication1
{
class MyCacheTest
{
public static void Main()
{
MyCache<UserInfo> mycache = new MyCache<UserInfo>();
//5秒更新一次缓存
mycache.timeoutSecond = 5000;
mycache.sql = "";
//启动缓存
mycache.StartCache();
for (int i = 0; i < 100; i++)
{
//读取缓存
Console.WriteLine("_______________读取缓存,缓存内容如下:");
List<UserInfo> userList = mycache.GetData();
foreach (UserInfo userInfo in userList)
{
Console.WriteLine(userInfo.ToString());
}
//1秒读取一次缓存
Thread.Sleep(1000);
}
}
}
}
这只是一个最简单的缓存系统,下一个版本希望能够实现如下功能:
1、支持key-value的查找、添加、删除。
2、添加缓存配置文件。
具体的配置文件如下:
<?xml version="1.0" encoding="utf-8" ?>
<SQLCommands>
<!--所有的用户缓存-->
<SQLCommand ListType="UserInfo" CommandString="SELECT * FROM UserInfo" CacheOverTime="0,5,0"></SQLCommand>
<!--未处理的订单缓存-->
<SQLCommand ListType="UnHandleOrder" CommandString="SELECT * FROM OrderInfo WHERE Orderstatus = 0" CacheOverTime="0,5,0"></SQLCommand>
</SQLCommands>