以前在给学生讲解COM+队列服务的时候,曾举了个例子:
比如你想给张三一记耳光,但张三不在眼前,明天才会来,可明天你又不在,怎么也碰不到张三,怎么办呢?这时候你可以使用COM+的队列服务,把你打耳光的动作用Recorder录入COM+队列中,等张三回来了,队列服务中的Player才真正播放这个动作,把这记耳光赏给张三。
例子比较粗俗,但想起张三那个倒霉样就想笑,科技发展那么快,说不准哪天就有这样的技术出现了。
在软件运行过程中,很多操作不需要进行同步调用,也不需要进行异步通知,这时候我想起来队列服务,忽然发现用C#的反射技术很容易实现,于是用C#实现了一个简单的队列,由Recorder、Listener、Player组成。
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
namespace ObjectQueue
{
#region Interface
/// <summary>
/// 记录器接口
/// </summary>
/// <typeparam name="T"></typeparam>
public interface iRecorder<T>
{
/// <summary>
/// 已记录条目总数
/// </summary>
long Total { get; }
void Record(T MethodInfo);
T GetNextItem();
}
/// <summary>
/// 监听器接口
/// </summary>
/// <typeparam name="T"></typeparam>
public interface iListener<T>
{
void Start(int interval);
}
/// <summary>
/// 播放器接口
/// </summary>
/// <typeparam name="T"></typeparam>
public interface iPlayer<T>
{
/// <summary>
/// 已播放条目总数
/// </summary>
long Total { get; }
void Play(T t);
}
#endregion
#region Implementation
public class cMethodInfo
{
public Object Obj { get; set; }
public string MethodName { get; set; }
public Object[] Params { get; set; }
public cMethodInfo(object obj, string methodName, object[] paramArray)
{
Obj = obj;
MethodName = methodName;
Params = paramArray;
}
}
public class cRecorder : iRecorder<cMethodInfo>
{
private long total;
private Queue<cMethodInfo> MethodInfoQue = new Queue<cMethodInfo>();
#region iRecorder<cMethodInfo> 成员
public void Record(cMethodInfo MethodInfo)
{
MethodInfoQue.Enqueue(MethodInfo);
Interlocked.Increment(ref total);
}
public cMethodInfo GetNextItem()
{
if (MethodInfoQue.Count > 0)
{
return MethodInfoQue.Dequeue();
}
else
{
return null;
}
}
public long Total
{
get
{
return total;
}
}
#endregion
}
public class cListener : iListener<cMethodInfo>
{
private Timer Timer1;
private iRecorder<cMethodInfo> mRecorder;
private iPlayer<cMethodInfo> mPlayer;
public cListener(iRecorder<cMethodInfo> Recorder, iPlayer<cMethodInfo> Player)
{
mRecorder = Recorder;
mPlayer = Player;
}
/// <summary>
/// cPlayer
/// </summary>
/// <param name="playInterval">播放频率,单位 毫秒,最小值为100</param>
public void Start(int interval)
{
if (interval < 100) interval = 100;
Timer1 = new Timer(CheckNewItem,
"", 1000, interval);
}
private void CheckNewItem(object obj)
{
cMethodInfo item = mRecorder.GetNextItem();
if (item != null)
{
mPlayer.Play(item);
}
}
}
/// <summary>
/// 独立线程中执行
/// </summary>
public class cPlayer : iPlayer<cMethodInfo>
{
private long total;
#region iPlayer<cMethodInfo> 成员
public void Play(cMethodInfo Method)
{
Type myType = Method.Obj.GetType();
MethodInfo displayInfoMethod = myType.GetMethod(Method.MethodName);
displayInfoMethod.Invoke(Method.Obj, Method.Params);
Interlocked.Increment(ref total);
}
public long Total
{
get { return total; }
}
#endregion
}
#endregion
}