源码
通过上面的调用方式,我们可以猜测到,FileWatcher类提供的构造函数应该是类似FileWatcher(string path, Func loadData)这样的代码,也就是FileStream到实体的转化还是自己类做,这样的话好处是可以自己控制一些特殊的逻辑,文件监控的通用功能在FileWatcher类里实现,我们来看一下源代码
public class FileWatcher<T> : IDisposable where T : class{
// 需要由配置文件转化成的对象类型
private T value;
// 通过文件流转化成实体的委托
private Func<FileStream, T> readMethod;
// 处理出错的时候,日志记录接口类型
private ILogger logger;
// 文件监控对象
private FileSystemWatcher fileWatcher;
// 加载文件或文件改变的时候触发此事件
private Lazy<ManualResetEvent> fileChangedEvent;
// 最后一次load失败的时间戳
private long lastFailedLoadTicks = DateTime.MaxValue.Ticks;
// 等待报告错误信息的时间
private static readonly TimeSpan FailedLoadGracePeriod = new TimeSpan(hours: 0, minutes: 1, seconds: 0);
// 第一次load所需要的最大时间,超过1分钟就抛出异常
private const int InitialLoadTimeoutMilliseconds = 60000;
// 构造函数
public FileWatcher(string path, Func<FileStream, T> readMethod, ILogger logger = null)
{
if (path == null)
throw new ArgumentNullException("path");
if (readMethod == null) throw new ArgumentNullException("readMethod");
this.Path = path;
this.readMethod = readMethod;
// KernelContainer.Kernel.Get是使用Ninject获取接口的实例,博友使用测试的话,需要处理一下这个代码
this.logger = logger ?? KernelContainer.Kernel.Get<ILogger>();
this.fileChangedEvent = new Lazy<ManualResetEvent>(Initialize);
}
// 资源回收相关的代码
#region IDisposable Members
~FileWatcher()
{
this.Dispose(false);
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool isDisposing)
{
if (isDisposing)
{
this.fileWatcher.Dispose();
this.fileWatcher = null;
}
}
#endregion
public string Path { get; private set; }
// 所生成的T对象
public T Value
{
get
{
if (!this.fileChangedEvent.Value.WaitOne(InitialLoadTimeoutMilliseconds))
{
throw new TimeoutException( String.Format("Failed to perform initial file load within {0} milliseconds: {1}", InitialLoadTimeoutMilliseconds, this.Path));
}
return Interlocked.CompareExchange(ref this.value, null, null);
}
private set
{
Interlocked.Exchange(ref this.value, value);
this.OnChanged(null);
}
}
// T更新的时候触发事件类型
public event EventHandler Changed;
// 触发事件
private void OnChanged(EventArgs e)
{
if (this.Changed != null)
{
this.Changed(this, e);
}
}
private DateTime LastFailedLoadTime
{
get
{
long ticks = Interlocked.CompareExchange(ref this.lastFailedLoadTicks, 0, 0);
return new DateTime(ticks);
}
set
{
Interlocked.Exchange(ref this.lastFailedLoadTicks, value.Ticks);
}
}
// 需要由配置文件转化成的对象类型
private T value;
// 通过文件流转化成实体的委托
private Func<FileStream, T> readMethod;
// 处理出错的时候,日志记录接口类型
private ILogger logger;
// 文件监控对象
private FileSystemWatcher fileWatcher;
// 加载文件或文件改变的时候触发此事件
private Lazy<ManualResetEvent> fileChangedEvent;
// 最后一次load失败的时间戳
private long lastFailedLoadTicks = DateTime.MaxValue.Ticks;
// 等待报告错误信息的时间
private static readonly TimeSpan FailedLoadGracePeriod = new TimeSpan(hours: 0, minutes: 1, seconds: 0);
// 第一次load所需要的最大时间,超过1分钟就抛出异常
private const int InitialLoadTimeoutMilliseconds = 60000;
// 构造函数
public FileWatcher(string path, Func<FileStream, T> readMethod, ILogger logger = null)
{
if (path == null)
throw new ArgumentNullException("path");
if (readMethod == null) throw new ArgumentNullException("readMethod");
this.Path = path;
this.readMethod = readMethod;
// KernelContainer.Kernel.Get是使用Ninject获取接口的实例,博友使用测试的话,需要处理一下这个代码
this.logger = logger ?? KernelContainer.Kernel.Get<ILogger>();
this.fileChangedEvent = new Lazy<ManualResetEvent>(Initialize);
}
// 资源回收相关的代码
#region IDisposable Members
~FileWatcher()
{
this.Dispose(false);
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool isDisposing)
{
if (isDisposing)
{
this.fileWatcher.Dispose();
this.fileWatcher = null;
}
}
#endregion
public string Path { get; private set; }
// 所生成的T对象
public T Value
{
get
{
if (!this.fileChangedEvent.Value.WaitOne(InitialLoadTimeoutMilliseconds))
{
throw new TimeoutException( String.Format("Failed to perform initial file load within {0} milliseconds: {1}", InitialLoadTimeoutMilliseconds, this.Path));
}
return Interlocked.CompareExchange(ref this.value, null, null);
}
private set
{
Interlocked.Exchange(ref this.value, value);
this.OnChanged(null);
}
}
// T更新的时候触发事件类型
public event EventHandler Changed;
// 触发事件
private void OnChanged(EventArgs e)
{
if (this.Changed != null)
{
this.Changed(this, e);
}
}
private DateTime LastFailedLoadTime
{
get
{
long ticks = Interlocked.CompareExchange(ref this.lastFailedLoadTicks, 0, 0);
return new DateTime(ticks);
}
set
{
Interlocked.Exchange(ref this.lastFailedLoadTicks, value.Ticks);
}
}