持久性保存技术的一点心得(C#)
按照通常的方法去保存数据的时候很容易会造成保存数据过大,占用内存过大。在这里探讨一种方法:
在工程里创建一个类,用来保存每类对象的数据(这里假设此类为:DataPackage)。在这个类中定义一个Hashtable ,用来储存每类对象的属性值。同时在此类中定义一些通常的操作,比如Undo,redo,这是非常方便的,比消息模式处理Undo,Redo方便多了。
在以后工程中定义需要序列化的类型时,可以只定义一个DataPackage类的对象字段(如DataPackage dataPackage = null)。然后将本应该定义的其他字段都定义成属性形式,在属性的实现里,去操作类的唯一字段dataPackage, 访问它的Hashtable来添加、删除等的操作。
经上面的处理,当需要保存数据时,只需要保存每个对象中的dataPackage对象的Hashtable即可。下面给出样例:
public class DataPackage
{
/// <summary>
/// The hashtable collecting all members data information
/// </summary>
protected Hashtable bag = null;
/// <summary>
/// The stack collecting the member names that has been set to new data
/// </summary>
[DoNotElementMapping]
protected Stack dustbinNames = null;
/// <summary>
/// The stack collecting the old member data that has been set to new data
/// </summary>
[DoNotElementMapping]
protected Stack dustbinValues = null;
/// <summary>
/// Get a member data
/// </summary>
/// <param name="memberName">the member name identify the data</param>
/// <param name="defaultValue">the default value for the member</param>
/// <returns>the data or null</returns>
public object Get(object memberName, object defaultValue)
{
if (bag != null)
{
if (!bag.ContainsKey(memberName))
{
bag.Add(memberName, defaultValue);
return defaultValue;
}
else
{
return bag[memberName];
}
}
else
{
return null;
}
}
/// <summary>
/// Set a member data
/// </summary>
/// <param name="memberName">the member name identify the data</param>
/// <param name="value">the data</param>
public void Set(object memberName, object value)
{
if (bag == null) bag = new Hashtable();
if (bag.ContainsKey(memberName))
{
if (dustbinNames == null)
{
dustbinNames = new Stack();
dustbinValues = new Stack();
}
dustbinNames.Push(memberName);
dustbinValues.Push(bag[memberName]);
bag.Remove(memberName);
}
bag.Add(memberName, value);
}
/// <summary>
/// Undo the last data set action
/// </summary>
public void UndoSet()
{
if (dustbinNames != null && dustbinNames.Count == dustbinValues.Count && dustbinNames.Count > 0)
{
if (bag == null)
{
bag = new Hashtable();
}
bag[dustbinNames.Pop()] = dustbinValues.Pop();
}
}
}
public class BaseElement
{
/// <summary>
/// The data bag is collecting the members of this class
/// </summary>
protected DataPackage bag = new DataPackage();
/// <summary>
/// Id of Element
/// </summary>
protected int id
{
get
{
object thisid = bag.Get("id", 0);
if (thisid == null)
{
return 0;
}
return (int)thisid;
}
set
{
bag.Set("id", value);
}
}
/// <summary>
/// Id of Element
/// </summary>
public int Id
{
get
{
return this.id;
}
}
/// <summary>
/// Name of Element
/// </summary>
protected string name
{
get
{
return (string)bag.Get("name", "");
}
set
{
bag.Set("name", value);
}
}
/// <summary>
/// Name of Element
/// </summary>
public virtual string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}
/// <summary>
/// Type of Element
/// </summary>
protected ElementTypes elementType
{
get
{
return (ElementTypes)bag.Get("elementType", ElementTypes.None);
}
set
{
bag.Set("elementType", value);
}
}
/// <summary>
/// Type of Element
/// </summary>
public ElementTypes ElementType
{
get
{
return this.elementType;
}
///only for class to interface
set
{
this.elementType = value ;
}
}
/// <summary>
/// Construct a BaseElement with an element type and an internal id
/// </summary>
/// <param name="internalID">The internal ID</param>
/// <param name="elementType">The element type</param>
public BaseElement(int internalID, ElementTypes elementType)
{
try
{
// Log
DebugLog.MethodBegin( "BaseElement", "BaseElement",
"internalID", internalID, "elementType", elementType );
// Construct
this.id = internalID;
this.elementType = elementType;
this.name = "";
// Log
DebugLog.MethodEnd( "BaseElement", "BaseElement", "Success" );
}
catch (Exception ex)
{
DebugLog.Fatal( ex );
}
}
/// <summary>
/// Construct a BaseElement with an element type and an internal id
/// </summary>
public BaseElement()
{
}
}
注:本文仅供本人做记录用。是同事的想法。本人认为很不错,所以记录下来,以免遗忘。