您的位置:首页 > 其它

委托通常可以应用到哪些场合

2014-08-27 11:15 211 查看
分析问题

  委托的功能和其名字非常类似,在设计中其思想在于把工作委派给其他特定的类型或者组件。委托的使用者可以理解为工作的分派者,在通常情况下使用者清楚地知道哪些工作需要执行、执行的结果又是什么,但是他却不会亲自地去做这些工作,而是恰当地把这些工作分派出去。

  在本节中,笔者将举一个日志读写的例子,来说明委托的实际应用。日志子系统在几乎所有的系统中都有所应用,在一般情况下,日志子系统的使用者希望的都是一个单一的方法,传入日志内容和日志类型,而日志系统会根据具体情况来进行写日志动作。对于日志系统的设计者来说,写一条日志可能需要包含一系列的工作,而日志系统决定把这些工作进行恰当的分派,这时就需要使用一个委托成员。下面代码展示了这个日志系统的简单实现方式。

using System;
using System.IO;
using System.Text;

namespace Test
{
/// <summary>
/// Log的类别
/// </summary>
public enum LogType
{
Debug,
Trace,
Info,
Warn,
Error,

}

/// <summary>
/// Log委托类型,由日志使用者直接执行来完成写日志的工作
/// </summary>
/// <param name="content"></param>
/// <param name="type"></param>
public delegate void Log(string content,LogType type);

public sealed partial class LogManager:IDisposable
{
//书写日志的组件
private Type _componentType;
//日志文件
private string _logFile;
//日志文件读写流
private FileStream _fs;
//用来写日志的委托
public Log writeLog;
//锁
private static object mutext = new object();

public LogManager()
{
writeLog = new Log(PreppareLogFile);
writeLog += OpenStream;

writeLog += AppendLocalTime;
writeLog += AppendSeperator;
writeLog += AppendComponentType;
writeLog += AppendSeperator;
writeLog += AppendType;
writeLog += AppendSeperator;
writeLog += AppendContent;
writeLog += AppendNewLine;
writeLog += CloseStream;
}

/// <summary>
/// 构造方法
/// </summary>
/// <param name="type">使用该日志的类型</param>
/// <param name="file">日志文件全路径</param>
public LogManager(Type type, string file)
: this()
{
_logFile = file;
_componentType = type;
}

/// <summary>
/// 释放FileStream对象
/// </summary>
public void Dispose()
{
if (_fs!=null)
{
_fs.Dispose();
}
GC.SuppressFinalize(this);
}

~LogManager()
{
if (_fs!=null)
{
_fs.Dispose();
}
}

#region 和日志文件有关的操作

/// <summary>
/// 如果日志文件不存在,则新建日志文件
/// </summary>
private void PreppareLogFile(string content, LogType type)
{
//只允许单线程创建日志文件
lock (mutext)
{
if (File.Exists(_logFile)==false)
{
using (FileStream fs = File.Create(_logFile))
{

}
}
}
}

/// <summary>
/// 打开文件流
/// </summary>
private void OpenStream(string content, LogType type)
{
_fs = File.Open(_logFile, FileMode.Append);
}

/// <summary>
/// 关闭文件流
/// </summary>
private void CloseStream(string content, LogType type)
{
_fs.Close();
_fs.Dispose();
}

#endregion

#region 和时间记录有关的操作

/// <summary>
/// 为日志添加当前UTC时间
/// </summary>
private void AppendUTCTime(string content, LogType type)
{
//得到当前UTC时间
string time = DateTime.Now.ToUniversalTime().ToString();
byte[] con = Encoding.Default.GetBytes(time);
_fs.Write(con, 0, con.Length);
}

/// <summary>
/// 为日志添加本地时间
/// </summary>
private void AppendLocalTime(string content, LogType type)
{
//得到本地时间
string time = DateTime.Now.ToLocalTime().ToString();
byte[] con = Encoding.Default.GetBytes(time);
_fs.Write(con, 0, con.Length);
}

#endregion

#region 和日志内容有关的操作

/// <summary>
/// 添加日志内容
/// </summary>
private void AppendContent(string content, LogType type)
{
byte[] con = Encoding.Default.GetBytes(content);
_fs.Write(con, 0, con.Length);
}

/// <summary>
/// 为日志添加组件类型
/// </summary>
private void AppendComponentType(string content, LogType type)
{
byte[] con = Encoding.Default.GetBytes(_componentType.ToString());
_fs.Write(con, 0, con.Length);
}

/// <summary>
/// 添加日志类型
/// </summary>
private void AppendType(string content, LogType type)
{
string typeString = string.Empty;
switch (type)
{
//针对不同的日志类型来记录
case LogType.Debug:
typeString = "Debug";
break;
case LogType.Trace:
typeString = "Trace";
break;
case LogType.Info:
typeString = "Info";
break;
case LogType.Warn:
typeString = "Warn";
break;
case LogType.Error:
typeString = "Error";
break;
default:
typeString = "";
break;
}
byte[] con = Encoding.Default.GetBytes(typeString);
_fs.Write(con, 0, con.Length);
}

#endregion

#region 和日志格式控制有关的操作

/// <summary>
/// 添加分隔符
/// </summary>
private void AppendSeperator(string content, LogType type)
{
byte[] con = Encoding.Default.GetBytes(" | ");
_fs.Write(con, 0, con.Length);
}

/// <summary>
/// 添加换行符
/// </summary>
private void AppendNewLine(string content, LogType type)
{
byte[] con = Encoding.Default.GetBytes("\r\n");
_fs.Write(con, 0, con.Length);
}

#endregion

#region 修改所使用的时间类型

/// <summary>
/// 设置使用UTC时间
/// </summary>
public void UseUTCTime()
{
writeLog = new Log(PreppareLogFile);
writeLog += OpenStream;
//这里添加记录UTC时间的方法
writeLog += AppendUTCTime;
writeLog += AppendSeperator;
writeLog += AppendComponentType;
writeLog += AppendSeperator;
writeLog += AppendType;
writeLog += AppendSeperator;
writeLog += AppendContent;
writeLog += AppendNewLine;
writeLog += CloseStream;
}

/// <summary>
/// 设置使用本地时间
/// </summary>
public void UseLocalTime()
{
writeLog = new Log(PreppareLogFile);
writeLog += OpenStream;
//这里添加记录本地时间的方法
writeLog += AppendLocalTime;
writeLog += AppendSeperator;
writeLog += AppendComponentType;
writeLog += AppendSeperator;
writeLog += AppendType;
writeLog += AppendSeperator;
writeLog += AppendContent;
writeLog += AppendNewLine;
writeLog += CloseStream;
}

#endregion

}
class UseLog
{
/// <summary>
/// 使用日志管理类型来记录日志
/// </summary>
static void Main()
{
//使用日志
using (LogManager logManager = new LogManager(Type.GetType("Test.UseLog"), @"D:\TestLog.txt"))
{
//记录日志
logManager.writeLog("新建了日志", LogType.Debug);
logManager.writeLog("写数据", LogType.Debug);
logManager.UseUTCTime();
logManager.writeLog("现在是UTC时间", LogType.Debug);
logManager.UseLocalTime();
logManager.writeLog("现在是本地时间", LogType.Debug);
logManager.writeLog("发生错误", LogType.Error);
logManager.writeLog("准备退出", LogType.Info);

}
}
}
}


  在上述代码所示的Log子系统中,使用了一个Log类型的委托来做所有的日志工作,而LogManager只需要管理这个委托,负责分派任务即可。代码中初始化委托成员的过程即是任务分派的过程,读者可能已经注意到,LogManager的UseUTCTime和UseLocalTime方法都对委托成员进行了重新分配,这可以理解为任务的再分配。

说明

  委托作为日志子系统的另一优点就在于可以灵活地分派任务,并且随时可以重新整理。读者可以尝试为LogManager添加其他功能,例如尝试提供其他编码的日志,并且提供重分配的公共方法来让使用者进行选择。

  下面是以上代码执行后的日志输出:

  


  

答案

  委托的应用场合通常是任务的执行者把细节工作进行再分配,执行者确切地知道什么工作将要被执行,但却把执行细节委托给其他组件、方法或者程序集。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐