【C#】缓存数据

namespace WpfCopy.Controls

{

    public class CacheFileEventArgs : EventArgs

    {

        public bool IsFaulted { get; private set; }

        public CacheFileModel CacheFile { get; private set; }





        public CacheFileEventArgs(CacheFileModel cacheFile)

        {

            CacheFile = cacheFile;

            IsFaulted = false;

        }



        public CacheFileEventArgs()

        {

            IsFaulted = true;

        }



    }





    public class CacheFileModel

    {

        public string RemoteFile { get; set; }

        public string LocalFile { get; set; }



        public DateTime CreateTime { get; set; }

        public DateTime LastUseTime { get; set; }

    }



    class FileCacheMgr

    {

        private const string CacheDir = "CacheFile";



        private const string CacheDataFile = "file.cache";



        /// <summary>

        /// 缓存数据文件的读写锁

        /// </summary>

        readonly object _cacheDataFileLock = new object();



        /// <summary>

        /// 管理缓存数据的锁

        /// </summary>

        readonly object _cacheLock = new object();



        /// <summary>

        /// 缓存数据任务的锁

        /// </summary>

        readonly object _cacheTaskLock = new object();



        /// <summary>

        /// 缓存数据字典

        /// </summary>

        Dictionary<string, CacheFileModel> _cacheDict = new Dictionary<string, CacheFileModel>();



        /// <summary>

        /// 下载任务字典

        /// </summary>

        readonly Dictionary<string, WeakDelegateCollection<CacheFileEventArgs>> _cacheTaskDict = new Dictionary<string, WeakDelegateCollection<CacheFileEventArgs>>();



        private static readonly FileCacheMgr instance = new FileCacheMgr();

        public static FileCacheMgr Instance { get { return instance; } }



        public FileCacheMgr()

        {



        }



        /// <summary>

        /// 读取缓存

        /// </summary>

        void LoadCacheData()

        {

            lock (_cacheDataFileLock)

            {

                if (!File.Exists(CacheDataFile) && Directory.Exists(CacheDir))

                    Directory.Delete(CacheDir, true);

                var xs = new XmlSerializer(typeof(List<CacheFileModel>));

                using (Stream stream = new FileStream(CacheDataFile, FileMode.Open, FileAccess.Read))

                {

                    var list = xs.Deserialize(stream) as List<CacheFileModel> ?? new List<CacheFileModel>();



                    _cacheDict = list.ToDictionary(m => m.RemoteFile);

                }

            }

        }

        /// <summary>

        /// 保存缓存

        /// </summary>

        void SaveCacheData()

        {

            lock (_cacheDataFileLock)

            {

                try

                {

                    var xs = new XmlSerializer(typeof(List<CacheFileModel>));

                    using (Stream stream = new FileStream(CacheDataFile, FileMode.Create, FileAccess.Write))

                    {

                        xs.Serialize(stream, _cacheDict.Values.ToList<CacheFileModel>());

                    }

                }

                catch (Exception)

                {

                    File.Delete(CacheDataFile);

                }

            }

        }

        /// <summary>

        /// 清除过期缓存

        /// </summary>

        public void ClearExpireCache()

        {

            try

            {

                List<string> clearList = new List<string>();



                foreach (var item in _cacheDict)

                {

                    if (DateTime.Now - item.Value.LastUseTime > TimeSpan.FromDays(7))

                        clearList.Add(item.Key);

                }



                foreach (var item in clearList)

                {

                    File.Delete(_cacheDict[item].LocalFile);

                    _cacheDict.Remove(item);

                }



                SaveCacheData();

            }

            catch (Exception ex)

            {

                throw ex;

            }

        }

        /// <summary>

        /// 添加缓存数据

        /// </summary>

        /// <param name="model"></param>

        public void AddCacheData(CacheFileModel model)

        {

            if (model == null)

                throw new ArgumentException("model");



            lock (_cacheLock)

            {

                if (_cacheDict.ContainsKey(model.RemoteFile) == false)

                {

                    _cacheDict.Add(model.RemoteFile, model);

                    SaveCacheData();

                }

            }

        }

        /// <summary>

        /// 删除缓存文件--

        /// </summary>

        /// <param name="model"></param>

        public void RemoveCacheData(CacheFileModel model)

        {

            if (model == null)

                throw new ArgumentException("model");



            if (File.Exists(model.LocalFile))

                File.Delete(model.LocalFile);



            if (_cacheDict.ContainsKey(model.RemoteFile))

            {

                _cacheDict.Remove(model.RemoteFile);

                SaveCacheData();

            }

        }



        /// <summary>

        /// 获取缓存数据,如果不存在,则创建下载任务

        /// </summary>

        /// <param name="remoteFile"></param>

        /// <param name="callback"></param>

        /// <param name="getFtpFunc"></param>

        void GetCacheFile(string remoteFile, EventHandler<CacheFileEventArgs> callback, Func<MyFtp> getFtpFunc)

        {



            if (_cacheDict.ContainsKey(remoteFile))

            {

                CacheFileModel cache = _cacheDict[remoteFile];

                if (File.Exists(cache.LocalFile))

                {

                    cache.LastUseTime = DateTime.Now;

                    SaveCacheData();



                    if (callback != null)

                    {

                        callback(this, new CacheFileEventArgs(cache));

                    }

                    return;

                }

                else

                {

                    _cacheDict.Remove(remoteFile);

                }

            }



            CreateDownLoadTask(remoteFile, getFtpFunc(), callback);

        }



        void CreateDownLoadTask(string remoteFile, MyFtp myFtp, EventHandler<CacheFileEventArgs> callBack)

        {

            lock (_cacheTaskLock)

            {

                bool exist = _cacheTaskDict.ContainsKey(remoteFile);

                AddCallBackToDictNoLock(remoteFile, callBack);

                if (exist == false)

                {

                    Task.Factory.StartNew(() =>

                    {

                        DownloadFileWork(remoteFile, myFtp, callBack);

                    }, TaskCreationOptions.PreferFairness);

                }

            }

        }



        void DownloadFileWork(string remoteFile, MyFtp myFtp, EventHandler<CacheFileEventArgs> callback)

        {

            string localFile = Path.Combine(CacheDir, Guid.NewGuid().ToString() + Path.GetExtension(remoteFile));



            string path = Path.GetDirectoryName(localFile);



            if (Directory.Exists(path) == false)

            {

                Directory.CreateDirectory(path);

            }

            var eventArgs = new CacheFileEventArgs();

            try

            {

                bool dlRet = myFtp.DownLoad(remoteFile, localFile);

                if (dlRet && File.Exists(localFile))

                {

                    var cacheModel = new CacheFileModel()

                    {

                        RemoteFile = remoteFile,

                        LocalFile = localFile

                    };

                    eventArgs = new CacheFileEventArgs(cacheModel);

                    AddCacheData(cacheModel);

                }

            }

            finally

            {

                try

                {

                    InvokeCallBack(remoteFile, eventArgs);

                }

                finally

                {

                    RemoveCallBack(remoteFile);

                }

            }

        }



        void AddCallBackToDictNoLock(string remoteFile, EventHandler<CacheFileEventArgs> callback)

        {

            if (_cacheTaskDict.ContainsKey(remoteFile) == false)

                _cacheTaskDict.Add(remoteFile, new WeakDelegateCollection<CacheFileEventArgs>());



            var weakEvent = _cacheTaskDict[remoteFile];

            weakEvent.WeakEvent += callback;

        }



        void RemoveCallBack(string remoteFile)

        {

            lock (_cacheTaskLock)

            {

                if (_cacheTaskDict.ContainsKey(remoteFile))

                    _cacheTaskDict.Remove(remoteFile);

            }

        }



        void InvokeCallBack(string remoteFile, CacheFileEventArgs args)

        {

            lock (_cacheTaskLock)

            {

                if (_cacheTaskDict.ContainsKey(remoteFile) == false)

                {

                    return;

                }



                _cacheTaskDict[remoteFile].Invoke(this, args);

            }

        }



    }

}

 

你可能感兴趣的:(C#)