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; }
}
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 = ("\t"),
OmitXmlDeclaration = true
};
string content;
using (var ms = new MemoryStream())
{
using (var xmlWriter = XmlWriter.Create(ms, settings))
{
XamlWriter.Save(Model, xmlWriter);
xmlWriter.Close();
}
ms.Position = ;
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);
}
}
这个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; } }
2.任务实现
public class DownloadApplet : IServerApplet
{ public string FilePath = @"D:\VS2012\Support\Main\Protal\Protal.Web.Framework\Data\File.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; }
}
现在这个任务就拿去用了。
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;
}
}
当然需要在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[] 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[];
var extensionname = sname.Split('.')[];
Response.Clear();
Response.ContentType = GetContentType(extensionname);
Response.AddHeader("Content-Disposition", "attachment;fileName=" + sname);
var b = pathstr.IndexOf('/') + ;
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 += ;
_applet.OnSave();
}
}
这样每次使用模型对象的时候不必再检索每个字段,其实就是序列化的一种应用场景,主要是将模型和存储分开了,模型你可以继续扩展,存储你可以实现xml的仓库,sqlserver的仓库,任务模块分开,便于控制。
这只是个小例子,马年第一次分享,喜欢就支持下,tks~
Xaml/Xml 实现对象与存储分离的更多相关文章
- Xamarin XAML语言教程对象元素的声明方式
Xamarin XAML语言教程对象元素的声明方式 XAML的对象元素的声明有两种形式,分别为包含属性的特性语法形式以及对象元素语法形式.在1.4小节中,我们看到了其中一种对XAML对象元素的声明方式 ...
- Atitit. 类与对象的存储实现
Atitit. 类与对象的存储实现 1. 类的结构和实现1 2. 类的方法属性都是hashtable存储的.2 3. Class的分类 常规类(T_CLASS), 抽象类(T_ABSTRACT T_C ...
- XML转换为对象操作类详解
//XML转换为对象操作类 //一,XML与Object转换类 using System.IO; using System.Runtime.Serialization.Formatters.Binar ...
- C# 使用XML序列化对象(二)
在C# 使用XML序列化对象(一)中描述了使用XML序列化对象的最简单的实现. 现在我们来看看稍微复杂一点的情况: 现有两个类:A和B,B是A的派生类,如下所示: public class A { p ...
- 李洪强iOS开发之OC[014] -对象的存储细节
// // main.m // 13 - 对象的存储细节 // // Created by vic fan on 16/7/9. // Copyright © 2016年 李洪强. All r ...
- c#xml序列化对象,xml标记都缩写了
最近最后一个接口,他们的格式很严格必须是如下格式 <message> <age>20</age> <name>张三</name> </ ...
- linux杂谈(十七):iscsi存储分离技术
1.iscsi简单介绍 iSCSI利用了TCP/IP的port 860 和 3260 作为沟通的渠道.透过两部计算机之间利用iSCSI的协议来交换SCSI命令,让计算机能够透过快速的局域网集线来 ...
- XML和对象属性互转的基类
本人做了一个XML和对象属性互转的基类,现在放上来有兴趣拿去看一下,用法很简单,声明一个BaseConversion的子类,该子类与你想转换的对象相对应,然后覆盖基类的两个虚方法,然后在里面写元素与对 ...
- 【安卓开发】为什么不能往Android的Application对象里存储数据
在一个App里面总有一些数据需要在多个地方用到.这些数据可能是一个 session token,一次费时计算的结果等.通常为了避免activity之间传递对象的开销 ,这些数据一般都会保存到持久化存储 ...
随机推荐
- Devexpress VCL Build v2015 vol 15.2 开始测试
增加了几个小玩意,与大版本变化根本无法匹配. 具体可以官网了解 https://www.devexpress.com/Subscriptions/New-2015.xml?product=vcl
- 更好更快更高效解析JSON说明
现在来一个实例解析类,直接就把解析JSON到QVariant去了.唯一不足的是没有搞错误处理,具体方法也请各位自行参考json-c的发行文档,这样比较方便叙述,STL或者Boost我都没有认真接触过, ...
- linux C学习笔记02--共享内存(进程同步)
system V下3中进程同步:共享内存(shared memory),信号量(semaphore)和消息队列(message queue) 调试了下午,终于调通啦! 运行./c.out 输出共享内存 ...
- LINUX下的拨号利器:wvdial和pppd —— 转载
wvdial是LINUX下的智能化拨号工具,利用wvdial和ppp可以实现linux下的轻松上网.在整个过程中wvdial的作用是拨号并等待提示,并根据提示输入相应的用户名和密码等认证信息:ppp的 ...
- VC MFC在CMFCToolBar工具栏中加入组合框
如何在CMFCToolBar工具栏中加入组合框等控件,且先看在线MSDN上怎么说的: 要增加一个组合框,需要完成以下步骤: 1.在工具栏资源中,增加一个对应ID资源号的按钮. 2.在主框架(mainf ...
- LoadRunner ---手动关联与预关联
手动关联 如果脚本很长,那么我们想找到一个脚本中哪些地方是需要关联的并不是一件容易的事情.这时,我们可以通过脚本对比的方法找 ...
- SVM2---核函数的引入
前边总结了线性SVM,最终转化为一个QP问题来求解.后来又考虑到非线性SVM,如果特征特别特别多的话,直接使用QP的话求解不了,我们经过一系列的转化,把这一问题转化为训练集大小n量级的QP问题. ht ...
- js 和 c# 方法互调
js访问c#代码 1 js <script type="javascript"><%=test()%></script> c# public ...
- 将C语课设传到了Github和Code上 2015-91-18
一直听说Git好使,以前捣鼓过没弄成,现在考完试了终于可以静下心来研究研究. 哎,我要是当时做课设的时候就用Git,也能省下不少事呢. 使用的Git教程,刚看个开头: 廖雪峰的Git教程 http:/ ...
- POJ 3348 - Cows 凸包面积
求凸包面积.求结果后不用加绝对值,这是BBS()排序决定的. //Ps 熟练了template <class T>之后用起来真心方便= = //POJ 3348 //凸包面积 //1A 2 ...