技术开发 频道

.NET项目:XML配置文件的另类读取方式

  源码

  通过上面的调用方式,我们可以猜测到,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);
        }
    }
0
相关文章