• Xaml/Xml 实现对象与存储分离


         刚开始用xml存储东西的时候都是不断的在xml文件里面添加或者修改xml的节点,这个是很常见的做法,这方面的博客也很多我也就不介绍了。但其实在小批量存储的时候我们可以直接将对象存进xml/xaml,使用的时候将整个对象加载出来,操作完成后再保存下去,这种做法没有什么技术难点,但我只是觉得更加的面相对象,模型和存储可以分开,模型的接口可以暴露出来,让前端的或者后台的调用,而存储可以换成xml/xaml和数据库。这样的好处就不言而喻了。

    一、创建仓库

        1.仓库的接口及基类

     /// <summary>
        /// Interface  Repository
        /// </summary>
        public interface IRepository
        {
            /// <summary>
            /// Loads this instance.
            /// </summary>
            void Load(Type type); // 可以加载不同的类型,xml,xaml
            /// <summary>
            /// Saves this instance.
            /// </summary>
            void Save();
    
            /// <summary>
            /// model
            /// </summary>
            object Model { get; set; }//我们要操作的对象
        }
     /// <summary>
        /// Class RepositoryBase
        /// </summary>
        public abstract class RepositoryBase : IRepository
        {
            /// <summary>
            /// Loads this instance.
            /// </summary>
            public virtual void Load(Type type)
            {
            }
    
            /// <summary>
            /// Saves this instance.
            /// </summary>
            public virtual void Save()
            {
            }
    
            /// <summary>
            /// model
            /// </summary>
            /// <value>The model.</value>
            public object Model { get; set; }
    
            /// <summary>
            /// 存储模型文件
            /// </summary>
            public string FileName { get; set; }
        }
    View Code

        2.Xaml仓库实现,在读取和写入的时候你还可以进行加密。特别是作为一些重要的工程配置文件,但又不想公开的时候。FileName 叫 FilePath更合适

     /// <summary>
        /// xaml仓库
        /// </summary>
        public class XamlRepository : RepositoryBase 
        {
            public XamlRepository()
            {
            }
    
            public XamlRepository(string fileName)
            {
                FileName = fileName;
            }
    
            public XamlRepository(string fileName, object model)
            {
                FileName = fileName;
                Model = model;
            }
    
            public override void Load(Type type)
            {
                if (!File.Exists(FileName))
                {
                    return;
                }
                var content = File.ReadAllText(FileName);
                //解密
                // var encrypt = new Encrypt();
                //  content = encrypt.DecryptString(content);
                using (var reader = XmlReader.Create(new MemoryStream(Encoding.UTF8.GetBytes(content))))
                {
                    Model = XamlReader.Load(reader);
                    reader.Close();
                }
            }
    
            public override void Save()
            {
                var dir = Path.GetDirectoryName(FileName);
                if (dir != null && !Directory.Exists(dir))
                {
                    Directory.CreateDirectory(dir);
                }
                var settings = new XmlWriterSettings
                {
                    Indent = true,
                    IndentChars = ("	"),
                    OmitXmlDeclaration = true
                };
                string content;
                using (var ms = new MemoryStream())
                {
                    using (var xmlWriter = XmlWriter.Create(ms, settings))
                    {
                        XamlWriter.Save(Model, xmlWriter);
                        xmlWriter.Close();
                    }
                    ms.Position = 0;
                    using (var reader = new StreamReader(ms))
                    {
                        content = reader.ReadToEnd();
                        reader.Close();
                    }
                    ms.Close();
                }
                //加密
                //  var encrypt = new Encrypt();
                // content = encrypt.EncryptString(content);
                File.WriteAllText(FileName, content);
            }
        }
    View Code

       这个xaml仓库就可以像一个基础设施来服务于模型了。xaml和xml都作为这种存储文件没有多大的区别,两者排版不同。xaml是一个对象一个节点,对象的属性将成为节点的属性,xml就是一层层的父子节点。

    二、创建模型

      模型设计就看你自身切实的考虑了,我这里例举一个文件下载的模型。这个模型有个集合类Filegroup。

        [Serializable]
        public class MyFileInfo
        {
            public int Id { get; set; }
            /// <summary>
            /// 文件名
            /// </summary>
            public string FileName { get; set; }
            /// <summary>
            /// 上传者ID
            /// </summary>
            public int UserId { get; set; }
            /// <summary>
            /// 上传时间
            /// </summary>
            public DateTime UploadTime { get; set; }
            /// <summary>
            /// 下载次数
            /// </summary>
            public int DownloadTimes { get; set; }
            /// <summary>
            /// 是否可见
            /// </summary>
            public bool IsVisible { get; set; }
    
            /// <summary>
            /// 文件类型
            /// </summary>
            public FileType FileType { get; set; }
    
    
            /// <summary>
            /// 对应的集合类
            /// </summary>
            [XmlIgnore, DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
            public FileGroup FileGroup { get; set; }
        }

      1.要加入序列化标签 [Serializable],

      2.[XmlIgnore, DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 可以忽略掉不想序列化的类。DesignerSerializationVisibility 这个枚举类型还有     Visible,Content,Visible和Hidden对应,Content用于集合元素,序列化它的内部类。

      3.当一个类型中包含有继承类的子类事,需要用XmlInclude标签。

       

       [XmlInclude(typeof(UserCustomAlarmFormat))]
        public class AlarmContentFormat{
    
        public List<AlarmPropertyFormat> AlarmPropertyFormats   
    
        }
    
    public class UserCustomAlarmFormat : AlarmPropertyFormat
    {
    
    public string Content { get; set; }
    public UserCustomAlarmFormat()
    {
    Name = "用户自定义";
    }
    }

     

     生成的文档会xsi的备注

     另外content的例子比如:

     public class FileGroup
        {
            private FileCollection _files;
         [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
            public FileCollection Files {
                get { return _files ?? (_files = new FileCollection()); }
                set { _files = value; }
            }
    //...... }

     这里的FileCollection是一个集合类,是list和字典的结合。这里可以直接换成List<T>

    三、任务加载

       现在仓库和模型都创建了,我们就可以用applet来封装,这个功能要用的时候就加载这个applet,不用的时候就拿掉。

      1.任务接口

     public interface IServerApplet
        {
            /// <summary>
            /// Called when [init].
            /// </summary>
            void OnInit();
            /// <summary>
            /// Called when [start].
            /// </summary>
            void OnStart();
            /// <summary>
            /// Called when [stop].
            /// </summary>
            void OnStop();
            /// <summary>
            /// Called when [exit].
            /// </summary>
            void OnExit();
    
            void Onload();
    
            /// <summary>
            /// Gets or sets the repository.
            /// </summary>
            /// <value>The repository.</value>
            RepositoryBase Repository { get; set; }
    
           
        }
    View Code

      2.任务实现

     public class DownloadApplet : IServerApplet
        {
     
            public  string FilePath = @"D:VS2012SupportMainProtalProtal.Web.FrameworkDataFile.xaml";
            public string RealFilePath = @"../../Content";
    
            #region 构造函数
    
            public DownloadApplet()
            {
    
            }
    
            public DownloadApplet(ProjectContext projectContext)
            {
                ProjectContext = projectContext;
            }
    
            #endregion
    
            #region 属性
    
            public FileGroup FileGroup { get; private set; }
    
         
            #endregion
    
    
            public void OnInit()
            {
                
                Onload();
            }
    
            public void OnStart()
            {
    
            }
    
            public void OnStop()
            {
    
            }
    
            public void OnExit()
            {
                OnSave();
            }
    
            public void Onload()
            {
                Repository = Repository ?? new XamlRepository(FilePath);
                Repository.Load(typeof(FileGroup));
                FileGroup = (Repository.Model as FileGroup) ?? new FileGroup();
                Logger.Debug("DownloadApplet 开始加载");
            }
    
            public void OnSave()
            {
                Repository.Model = FileGroup = FileGroup ?? new FileGroup();
                Repository.Save();
            }
          
            public RepositoryBase Repository { get; set; }
        }
    View Code

    现在这个任务就拿去用了。 

     3.任务管理

     当任务很多的时候,可以再创建一个AppletManager类 来管理这些任务,决定哪些加载哪些不加载。这里我默认加载了DownloadApplet

     public  class AppletManager
        {
            private static AppletManager _instance;
            private List<IServerApplet> _applets;
    
            public AppletManager()
            {
                Applets.Add(new DownloadApplet());
            }
    
            public List<IServerApplet> Applets
            {
                get { return _applets??(_applets=new List<IServerApplet>()); }
                set { _applets = value; }
            }
    
            /// <summary>
            /// 启动工程
            /// </summary>
            public void Start()
            {
                foreach (IServerApplet applet in Applets)
                    applet.OnStart();
            }
    
            /// <summary>
            /// 停止工程
            /// </summary>
            public void Stop()
            {
                foreach (IServerApplet applet in _applets)
                    applet.OnStop();
                foreach (IServerApplet applet in _applets)
                    applet.OnExit();
                _applets.Clear();
            }
    
            /// <summary>
            /// 退出工程,开发时使用
            /// </summary>
            public void Exit()
            {
                foreach (IServerApplet applet in _applets)
                    applet.OnExit();
                _applets.Clear();
            }
    
            public static AppletManager GetInstance(bool always = true)
            {
                if (_instance == null && always)
                    _instance = new AppletManager();
                return _instance;
            }
        }
    View Code

     当然需要在Global.asax中启动。

         protected void Application_Start()
            {
    ......... //
    var proj = AppletManager.GetInstance(); proj.Start(); Logger.Debug("工程开始启动"); }

    四、应用

      这里我是在MVC的controller里面调用,模型对象加载之后就可以直接用了。需要的时候save一下。

        public class FileController : Controller
        {
           
            // GET: /Fileprivate readonly DownloadApplet _applet = AppletManager.GetInstance().Applets[0] as DownloadApplet;
            private readonly FileGroup _fileGroup;
            public FileController()
            {
                if (_applet == null) return;
                _applet.Onload();
                _fileGroup = _applet.FileGroup ?? new FileGroup();
            }/// <summary>
            /// TransmitFile的方式下载   
            /// </summary>
            /// <param name="pathstr"></param>
            public void TransmitFileLoad(string pathstr)
            {
                var strs = pathstr.Split('/');
                var sname = strs[4];
                var extensionname = sname.Split('.')[1];
                Response.Clear();
                Response.ContentType = GetContentType(extensionname);
                Response.AddHeader("Content-Disposition", "attachment;fileName=" + sname);
                var b = pathstr.IndexOf('/') + 1;
                var serverpath = pathstr.Substring(b, pathstr.Length - b);
                string fileName = Server.MapPath(serverpath);
                Response.TransmitFile(fileName);
                Response.End();
    
                //统计次数
                var file = _fileGroup.Files.Find(m => m.FileName == sname);
                if (file != null)
                {
                    file.DownloadTimes += 1;
                    _applet.OnSave();
                }
            }

    这样每次使用模型对象的时候不必再检索每个字段,其实就是序列化的一种应用场景,主要是将模型和存储分开了,模型你可以继续扩展,存储你可以实现xml的仓库,sqlserver的仓库,任务模块分开,便于控制。

         这只是个小例子,马年第一次分享,喜欢就支持下,tks~ 

  • 相关阅读:
    Oracle:SQL语句--撤销用户权限
    Oracle:SQL语句--给用户赋权限
    RSTP端口状态迁移过程详解
    LSB算法分析与实现
    工厂方法模式
    Ceasar
    区域性名称和标识符
    Packet Tracer网络模拟实验实记
    H3C-OSPF
    H3C-RIP
  • 原文地址:https://www.cnblogs.com/stoneniqiu/p/3542646.html
Copyright © 2020-2023  润新知