有时,我们在开发的时候,会遇到一些关于日志记录的功能。并且,它们可能是独立于系统业务逻辑的,那么我们就可以将日志做成组件的形式,以方便复用。
以下采用工厂方法模式,来实现日志组件的设计,并保证对功能的扩展不会改变已有的实现。
我们实现三种日志记录类型:错误日志记录、按钮点击日志记录、操作日志记录。
首先,我们创建一个“抽象工厂”【其实是各实例工厂都必须实现的Log接口】,既然是日志记录,那么就需要有日志的实体了。也就是LogEntity,它是一个“抽象实体”,因为不同类型的日志,需要不同的日志实体,所以这里采用LogEntity作为抽象实体,来派生出各具体类型的日志实体。
实现如下:
public interface ILogFactory
{
void Log(LogEntity logEntity);
}
/// <summary>
/// 日志实体(抽象基类)
/// </summary>
public abstract class LogEntity
{
public override string ToString()
{
return "LogEntity(abstract class)";
}
}
以下是各个实例工厂、和日志实体,实现各自的日志记录逻辑:
/// <summary>
/// 记录错误日志实体类
/// </summary>
public class ErrorEntity:LogEntity
{
/// <summary>
/// 编号
/// </summary>
public string ID { get; set; }
/// <summary>
/// 用户编号
/// </summary>
public string UserID { get; set; }
/// <summary>
/// 页面URL
/// </summary>
public string PageUrl { get; set; }
/// <summary>
/// 错误信息
/// </summary>
public string Msg { get; set; }
/// <summary>
/// 发生时间
/// </summary>
public DateTime OperateTime { get; set; }
}
public class ErrorFactory : ILogFactory
{
private const string FullClassName = "LogComponent.ErrorFactory";
public void Log(LogEntity logEntity)
{
#region check args
if (logEntity == null)
{
throw new ArgumentNullException(string.Format("The Method in {0} occur ArgumentNullException", FullClassName));
}
ErrorEntity innerEntity = logEntity as ErrorEntity;
if (innerEntity == null)
{
throw new NullReferenceException(string.Format("The Method in {0} occur NullReferenceException.Because of converting type.", FullClassName));
}
if (string.IsNullOrEmpty(innerEntity.Msg))
{
throw new Exception(string.Format("The Method in {0} occur logic Exception. Because of the error message is not nullable", FullClassName));
}
#endregion
//记录日志
string sql = @"INSERT INTO SYSTEMERRORINFO(SE_USERID,SE_PAGEURL,SE_MESSAGE,SE_OPERATETIME) values (:SE_USERID,:SE_PAGEURL,:SE_MESSAGE,:SE_OPERATETIME)";
OracleParameter[] parameters = new OracleParameter[]
{
new OracleParameter(":SE_USERID",innerEntity.UserID==null?"":innerEntity.UserID),
new OracleParameter(":SE_PAGEURL",innerEntity.PageUrl==null?"":innerEntity.PageUrl),
new OracleParameter(":SE_MESSAGE",innerEntity.Msg==null?"":innerEntity.Msg),
new OracleParameter(":SE_OPERATETIME",innerEntity.OperateTime==DateTime.MinValue?DateTime.Now:innerEntity.OperateTime)
};
OracleHelper.ExecuteNonQuery(OracleHelper.ConnectionStringLocalTransaction, CommandType.Text, sql, parameters);
}
}
/// <summary>
/// 点击按钮统计--其中ButtonName为必填字段
/// </summary>
public class ClickCountEntity:LogEntity
{
/// <summary>
/// 记录编号
/// </summary>
public string ID { get; set; }
/// <summary>
/// 用户ID
/// </summary>
public string UserID { get; set; }
/// <summary>
/// 页面Url
/// </summary>
public string PageUrl { get; set; }
/// <summary>
/// 操作时间
/// </summary>
public DateTime OperateTime { get; set; }
/// <summary>
/// 路径名称
/// </summary>
public string PathName { get; set; }
/// <summary>
/// 按钮名称
/// </summary>
public string ButtonName { get; set; }
}
public class ClickCountFactory:ILogFactory
{
private const string FullClassName = "LogComponent.ClickCountFactory";
private ErrorEntity errorEntity = null;
public void Log(LogEntity logEntity)
{
//check args
if (logEntity==null)
{
errorEntity = new ErrorEntity();
errorEntity.Msg = string.Format("The method in {0} occur ArgumentNullException.Because of the arg: logEntity is not nullable.", FullClassName);
ILogFactory logFactory = new ErrorFactory();
logFactory.Log(errorEntity);
throw new ArgumentNullException(string.Format("The method in {0} occur ArgumentNullException.Because of the arg: logEntity is not nullable.", FullClassName));
}
ClickCountEntity innerEntity = logEntity as ClickCountEntity;
if (innerEntity==null)
{
errorEntity = new ErrorEntity();
errorEntity.Msg = string.Format("The method in {0} occur NullReferenceException.Becaues of converting type", FullClassName);
ILogFactory logFactory = new ErrorFactory();
logFactory.Log(errorEntity);
throw new NullReferenceException(string.Format("The method in {0} occur NullReferenceException..Becaues of converting type", FullClassName));
}
if (String.IsNullOrEmpty(innerEntity.ButtonName))
{
errorEntity = new ErrorEntity();
errorEntity.Msg = string.Format("The method in {0} occur Exception.Because of the field ButtonName is not nullable.", FullClassName);
ILogFactory logFactory = new ErrorFactory();
logFactory.Log(errorEntity);
throw new Exception(string.Format("The method in {0} occur Exception.Because of the field ButtonName is not nullable.", FullClassName));
}
string sql = @"INSERT INTO buttonclickstatistic
(bs_userid, bs_pageurl, bs_buttonid, bs_operatetime, bs_pathname, bs_buttonname)
VALUES
(:v_bs_userid, :v_bs_pageurl, :v_bs_buttonid, :v_bs_operatetime, :v_bs_pathname, :v_bs_buttonname)";
OracleParameter[] parameters = new OracleParameter[]{
new OracleParameter(":v_bs_userid",innerEntity.UserID==null?"":innerEntity.UserID),
new OracleParameter(":v_bs_pageurl",innerEntity.PageUrl==null?"":innerEntity.PageUrl),
new OracleParameter(":v_bs_buttonid",innerEntity.ID==null?"":innerEntity.ID),
new OracleParameter(":v_bs_operatetime",innerEntity.OperateTime),
new OracleParameter(":v_bs_pathname",innerEntity.PathName==null?"":innerEntity.PathName),
new OracleParameter(":v_bs_buttonname",innerEntity.ButtonName)
};
try
{
OracleHelper.ExecuteNonQuery(OracleHelper.ConnectionStringLocalTransaction, CommandType.Text, sql, parameters);
}
catch (Exception ex)
{
errorEntity = new ErrorEntity();
errorEntity.Msg = ex.Message + ex.StackTrace;
ILogFactory logFactory = new ErrorFactory();
logFactory.Log(errorEntity);
throw;
}
}
}
/// <summary>
/// 操作日志实体类--其中Msg为必填字段
/// </summary>
public class OperatingEntity:LogEntity
{
/// <summary>
/// 记录编号
/// </summary>
public string ID { get; set; }
/// <summary>
/// 用户Id
/// </summary>
public string UserID { get; set; }
/// <summary>
/// 操作日志
/// </summary>
public string Msg { get; set; }
/// <summary>
/// 操作时间
/// </summary>
public DateTime OperatingTime { get; set; }
/// <summary>
/// 登陆时间
/// </summary>
public DateTime LoginTime { get; set; }
/// <summary>
/// 下线时间
/// </summary>
public DateTime LogoutTime { get; set; }
}
public class OperatingFactory:ILogFactory
{
private const string FullClassName = "LogComponent.OperatingFactory";
private ErrorEntity errorEntity = null;
public void Log(LogEntity logEntity)
{
//check args
if (logEntity==null)
{
errorEntity = new ErrorEntity();
errorEntity.Msg = string.Format("The method in {0} occur ArgumentNullException.Because of the arg: {1} is not nullable", FullClassName, "logEntity");
ILogFactory logFactory = new ErrorFactory();
logFactory.Log(errorEntity);
throw new ArgumentNullException(string.Format("The method in {0} occur ArgumentNullException.Because of the arg: {1} is not nullable", FullClassName, "logEntity"));
}
OperatingEntity innerEntity = logEntity as OperatingEntity;
if (innerEntity==null)
{
errorEntity = new ErrorEntity();
errorEntity.Msg = string.Format("The method in {0} occur NullReferenceException.Because of Converting type.", FullClassName);
ILogFactory logFactory = new ErrorFactory();
logFactory.Log(errorEntity);
throw new NullReferenceException(string.Format("The method in {0} occur NullReferenceException.Because of Converting type.", FullClassName));
}
if (string.IsNullOrEmpty(innerEntity.Msg))
{
errorEntity = new ErrorEntity();
errorEntity.Msg = string.Format("The method in {0} occur Exception.Because of the field:Msg is not nullable.",FullClassName);
ILogFactory logFactory = new ErrorFactory();
logFactory.Log(errorEntity);
throw new Exception(string.Format("The method in {0} occur Exception.Because of the field:Msg is not nullable.", FullClassName));
}
//记录日志
string sql = @"INSERT INTO operatinglog(ol_uf_id,ol_msg,ol_op_time,ol_li_time,ol_lo_time)
VALUES(:ol_uf_id,:ol_msg,:ol_op_time,:ol_li_time,:ol_lo_time)";
OracleParameter[] paras = new OracleParameter[]
{
new OracleParameter(":ol_uf_id",innerEntity.UserID==null?"":innerEntity.UserID),
new OracleParameter(":ol_msg",innerEntity.Msg),
new OracleParameter(":ol_op_time",innerEntity.OperatingTime),
new OracleParameter(":ol_li_time",innerEntity.LoginTime),
new OracleParameter(":ol_lo_time",innerEntity.LogoutTime),
};
try
{
OracleHelper.ExecuteNonQuery(OracleHelper.ConnectionStringLocalTransaction, CommandType.Text, sql, paras);
}
catch (Exception ex)
{
errorEntity = new ErrorEntity();
errorEntity.Msg = ex.Message + ex.StackTrace;
ILogFactory logFactory = new ErrorFactory();
logFactory.Log(errorEntity);
throw;
}
}
}
在客户端调用的时候,你需要先new 一个你需要的具体的日志实体,然后设置它的属性,比如:
OperatingEntity entity=new OperatingEntity();
//set Property
entity.OperatingTime=DateTime.Now;
.....
然后提供你的实例工厂:
ILogFactory factory=new OperatingFactory();
factory.Log(entity);
扩展的时候,你需要构建你新的日志实体类和新的实例工厂,来实现你的记录逻辑。
原有的实现都无需改动。