ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(十二) 代码重构使用反射工厂解耦(一)缓存切换
前言
上一篇中,我们用了反射工厂来解除BLL和UI层耦合的问题。当然那是最简单的解决方法,再复杂一点的程序可能思路相同,但是在编程细节中需要考虑的就更多了,比如今天我在重构过程中遇到的问题。也是接下来我要解决的问题,缓存模块。为什么要解决这个问题呢,由于我们有些下载代码运行的小伙伴,发现怎么运行报错,原来是没有装redis。可是我只想看layim和signalr代码而已啊,不想装什么redis。那么基于昨天的经验,我把缓存模块同样提取出接口,然后加了一个原始的cache层。这个cache是基于System.Web.Caching.Cache来实现的。
实现思路
正如前言中所说,实现思路还是利用反射工厂,读取用户的配置来反射动态生成对象。Cache代码结构调整如下:
首先说明一下,由于接口内部方法目前只是根据项目需要来设计,可能不全面或者不够灵活,不过没关系,后期可以完善。目前接口(ICache)中包含如下方法:
public interface ICache
{ /// <summary>
/// 获取缓存,根据key
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns>返回获取到的值</returns>
T Get<T>(string key);
/// <summary>
/// 增加缓存
/// </summary>
/// <typeparam name="T">T</typeparam>
/// <param name="key">key</param>
/// <param name="value">value</param>
/// <returns>添加成功返回true,否则返回false</returns>
bool Set<T>(string key, T value);
bool Set<T>(string key, T value, DateTimeOffset offset);
/// <summary>
/// 判断key是否存在
/// </summary>
/// <param name="key">key</param>
/// <returns>存在返回true,否则返回false</returns>
bool Exists(string key);
/// <summary>
/// 删除缓存
/// </summary>
/// <param name="key"></param>
/// <returns>返回是否删除成功,true或者false</returns>
bool Delete(string key); /// <summary>
/// 获取哈希表中的值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="hashKey"></param>
/// <param name="key"></param>
/// <returns></returns>
T HashGet<T>(string hashKey, string key);
/// <summary>
/// 设置哈希缓存值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="hashKey">hashKey</param>
/// <param name="key">key</param>
/// <param name="value">value</param>
/// <returns>返回是否设置成功</returns>
bool HashSet<T>(string hashKey, string key, T value);
/// <summary>
/// 删除哈希缓存中的某个key
/// </summary>
/// <param name="hashKey"></param>
/// <param name="key"></param>
/// <returns>返回是否删除成功</returns>
bool HashDelete(string hashKey, string key); }
很简单的几个方法,相信复杂的项目或者需求肯定要有更多的功能。这里姑且不讨论。然后我们按照上图中新建文件夹,分别对应我们要切换的Cache类型。比如,我新建了,Memcached,Redis,Memory三个文件夹,前两个不用说,第三个就是我们使用框架自带的Cache。下面的代码是我参照网络上的一段文章又简单包装了一下写的。这里写这个Cache只是为了后续提到的,我们能够自由切换而已。能用第三方的缓存还是用第三方的。代码如下:(实现接口中的方法)
public class Cache : ICache
{ private static System.Web.Caching.Cache _cache;
const int defaultTime = * ;//一天
public Cache() {
//初始化
_cache = HostingEnvironment.Cache;
SaveTime = defaultTime;
}
public static double SaveTime
{
get;
set;
}
public bool Delete(string key)
{
var obj =_cache.Remove(key);
return obj != null;
} public bool Exists(string key)
{
return true;
} public T Get<T>(string key)
{
if (string.IsNullOrEmpty(key)) {
return default(T);
}
return (T)_cache.Get(key);
} public bool HashDelete(string hashKey, string key)
{
Hashtable table = Get<Hashtable>(hashKey);
if (table == null) { return true; } else {
if (table.ContainsKey(key)) {
table.Remove(key);
}
}
return true;
} public T HashGet<T>(string hashKey, string key)
{
Hashtable table = Get<Hashtable>(hashKey);
if (table != null)
{
var value = table[key];
if (value == null) {
return default(T);
}
return (T)value;
}
return default(T);
} public bool HashSet<T>(string hashKey, string key, T value)
{
//这里就是用hashtable做哈希保存
Hashtable table = Get<Hashtable>(hashKey);
if (table == null)
{
table = new Hashtable();
table.Add(key, value);
}
else
{
if (table.ContainsKey(key))
{
table[key] = value;
}
else
{
table.Add(key, value);
}
}
return Set(hashKey, table);
} #region
private void Insert(string key, object value, CacheDependency dependency, CacheItemPriority priority, CacheItemRemovedCallback callback)
{
_cache.Insert(key, value, dependency,System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(SaveTime), priority, callback);
} private void Insert(string key, object value, CacheDependency dependency, CacheItemRemovedCallback callback)
{
Insert(key, value, dependency, CacheItemPriority.Default, callback);
} private void Insert(string key, object value, CacheDependency dependency)
{
Insert(key, value, dependency, CacheItemPriority.Default, null);
} private void Insert(string key, object value)
{
Insert(key, value, null, CacheItemPriority.Default, null);
}
#endregion
public bool Set<T>(string key, T value)
{
Insert(key, value);
return true;
} public bool Set<T>(string key, T value, DateTimeOffset offset)
{
SaveTime = offset.Offset.Minutes;
Insert(key, value);
SaveTime = defaultTime;
return true;
} }
这样的话,我们同样用上一篇文章中写的方法来生成对用的ICache对象。
public class LayIMCacheFactory : LayIMFactory
{
public LayIMCacheFactory() {
asemmblyPath = "LayIM.Cache.Classes.{0}.{1},LayIM.Cache";
_type = "CacheType";
} public ICache CreateCache()
{
return Create<ICache>(FactoryClasses.Cache);
} public LayIMCache CreateLayIMCache()
{
ICache cache = CreateCache();
return new LayIMCache(cache);
}
}
可以看到,上述代码中,CreateLayIMCache方法中返回的是LayIMCache,是因为LayIMCache相当于业务层了,虽然也做了接口,但是(暂时)没有必要再区分了,因为,在构造函数中,我把ICache的实例传给LayIMCache中,然后内部调用相应的Cache方法,然后再最外部调用LayIMCache。可能把大家绕晕了。画个图更形象一些.(我也不会UML图,实在惭愧,将就看吧~)
现在我们来演示一下。怎么能看出不同呢,由于Redis使能够将我们存的缓存数据持久化的。而Memory的这个Cache只要程序停了,他就消失了。那么,我们可以通过验证登录token的方法来测试。首先Redis不必说。我们更改web.config中的CacheType值。
<!--缓存类型,Redis Memory,Memcached-->
<add key="CacheType" value="Memory" />
这里要注意,不论是Memory还是Redis或者其他,这里的配置字母一定要写正确,否则反射生成实例的时候会报错。
我们运行一下,打断点调试:
这时候我们在关闭程序,重新运行调试,我们走到token验证,看一下内容,已经没有了,如下图,验证已经进入非授权条件内。
总结
本篇已经接近尾声了,原来写代码写多了,头脑真的会升华。以前看设计模式中的代码压根体会不到其中的奥妙,如今专门做一下代码重构工作才能真正体验到代码设计的精妙之处。骚年还需要努力啊。今天的代码重构工作就到此结束,不想装Redis的同学赶紧试试用这个方法切换缓存吧。不知道我在说些什么的同学可以移步这里哦:
ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室 实战系列(不断更新中)
ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(十二) 代码重构使用反射工厂解耦(一)缓存切换的更多相关文章
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(二) 之 ChatServer搭建,连接服务器,以及注意事项。
上篇:ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(一) 之 基层数据搭建,让数据活起来(数据获取) 上一篇我们已经完成了初步界面的搭建工作,本篇将介绍IM的核心内容 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室 实战系列
ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言 http://www.cnblogs.com/panzi/p/5742089.html ASP.NET S ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(一) 之 基层数据搭建,让数据活起来(数据获取)
大家好,本篇是接上一篇 ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言 ASP.NET SignalR WebIM系列第二篇.本篇会带领大家将 LayIM ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室 实战系列(不断更新中)
项目简介 利用ASP.NET SignalR技术与Layim前端im框架实现的一个简单的web聊天室,包括单聊,群聊,加好友,加群,好友搜索,管理,群组管理,好友权限设置等功能.涉及技术: Elast ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室 实战系列(内容已过期,阅读请慎重)
项目简介 利用ASP.NET SignalR技术与Layim前端im框架实现的一个简单的web聊天室,包括单聊,群聊,加好友,加群,好友搜索,管理,群组管理,好友权限设置等功能.涉及技术: Elast ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言
前端时间听一个技术朋友说 LayIM 2.0 发布了,听到这个消息抓紧去官网看了一下.(http://layim.layui.com/)哎呀呀,还要购买授权[大家支持一下哦],果断买了企业版,喜欢钻研 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(三) 之 实现单聊,群聊,发送图片,文件。
上篇讲解了如何搭建聊天服务器,以及客户端js怎么和layui的语法配合.服务器已经连接上了,那么聊天还会远吗? 进入正题,正如上一篇提到的我们用 Client.Group(groupId)的方法向客户 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(四) 之 用户搜索(Elasticsearch),加好友流程(1)。
前面几篇基本已经实现了大部分即时通讯功能:聊天,群聊,发送文件,图片,消息.不过这些业务都是比较粗犷的.下面我们就把业务细化,之前用的是死数据,那我们就从加好友开始吧.加好友,首先你得知道你要加谁.L ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(五) 之 加好友,加群流程,消息管理和即时消息提示的实现
前言 前前一篇留了个小问题,在上一篇中忘了写了,就是关于LayIM已经封装好的上传文件或者图片的问题.对接好接口之后,如果上传速度慢,界面就会出现假死情况,虽然文件正在上传.于是我就简单做了个图标替代 ...
随机推荐
- jQuery编程最佳实践笔记
优化选择器 选择器优化已经不如从前那么重要,因为更多的浏览器实现了document.querySelectorAll()方法,所以选择的重担由jQuery转移到了浏览器. 但是仍然有一些技巧是需要 ...
- 自定义iOS7导航栏背景,标题和返回按钮文字颜色
在iOS7下,默认导航栏背景,颜色是这样的,接下来我们就进行自定义,如果你仅仅是更改一下背景和颜色,代码会很简单,不需要很复杂的自定义View来替代leftBarItem 更改导航栏的背景和文字Col ...
- C语言程序设计第10堂作业
一.本次课主要内容: 本次课程学习数组,一种最基本的构造类型,它是一组相同类型数据的有序集合.数组中的元素在内存中连续存放,每个元素都属于同一种数据类型,用数组名和下标可以唯一地确定数组元素: (1) ...
- 位置指纹(LF)定位技术简介-室内定位
信号的多径传播对环境具有依赖性,呈现出非常强的特殊性.对于每个位置而言,该位置上信道的多径结构是惟一的,终端发射的无线电渡经过反射和折射,产生与周围环境密切相关的特定模式的多径信号,这样的多径 ...
- firefox vimperator插件
firefox vimperator插件实在是强大,最喜欢的几个功能做个笔记. 如何复制网页上的文字:c进入caret模式,定位cursor到要复制的开始位置--v进入visual模式,用hjkl键选 ...
- Linux 知识框架
Linux要点 一.Linux的基本要求 1. 掌握至少50个以上的常用命令. 2. 熟悉Gnome/KDE等X-windows桌面环境操作 . 3. 掌握.tgz..rpm等软件包的常用安装方法 4 ...
- SQL 事务
/*========================事务==============================*/begin tran--开始事务 --开始写流程语句 --语句写完之后if @@ ...
- 2014嘉杰信息杯ACM/ICPC湖南程序设计邀请赛暨第六届湘潭市程序设计竞赛
比赛链接: http://202.197.224.59/OnlineJudge2/index.php/Contest/problems/contest_id/36 题目来源: 2014嘉杰信息杯ACM ...
- Xcode6中如何去掉默认的Main.storyboard
xcode 6取消了 Empty Application 模板来创建一个工程,创建出来的有工程多了Main.storyboard,默认加载Main.storyboard,但是有很多人还想用代码来实现U ...
- iOS Block循环引用
在介绍block循环引用前我们先了解一下typeof. typeof是什么??? typeof 是一个一元运算,放在一个运算数之前,运算数可以是任意类型. 它返回值是一个字符串,该字符串说明运算数的类 ...