Model只有两种,
BaseEntity子类,手动读取一条数据进内存
ShareEntity子类,一次读取所有数据进内存
Model的protobuf属性有三种
基本类型,数值和string
EntityChangeEvent子类对象,相当于嵌套的数据结构
CacheDictionary<基本类型, EntityChangeEvent子类>
CacheList<EntityChangeEvent子类>
参考SCUT源代码的Clone略有修改:
private static object Clone(object clone, object model, string flavor, Dictionary<object, object> cloneDictionary)
{
System.Diagnostics.Debug.Assert(null != clone);
if (clone == null)
return null;
object value = null;
foreach (PropertyInfo prop in model.GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.SetProperty | BindingFlags.GetField | BindingFlags.SetField))
{
if (!prop.CanRead ||
!prop.CanWrite ||
ExcludeProperty(model, flavor, prop) ||
prop.GetIndexParameters().Length > 0
)
{
continue;
}
if (prop.PropertyType.GetInterface(typeof(IDictionary<,>).Name) != null)
{
var origCollection = prop.GetValue(model, null) as IEnumerable;
dynamic cloneCollection = null;
if (origCollection != null)
{
cloneCollection = FastActivator.Create(prop.PropertyType);
foreach (dynamic elem in origCollection)
{
var key = Clone(elem.Key, flavor, cloneDictionary);
var obj = Clone(elem.Value, flavor, cloneDictionary);
cloneCollection.Add(key, obj);
}
}
prop.SetValue(clone, cloneCollection, null);
continue;
}
if (prop.PropertyType.GetInterface(typeof(ICollection<>).Name) != null)
{
var origCollection = prop.GetValue(model, null) as IEnumerable;
if (origCollection == null)
{
prop.SetValue(clone, null, null);
continue;
}
dynamic cloneCollection = null;
if (prop.PropertyType.IsArray)
{
//cloneCollection = (origCollection as Array).Clone();
Type elemType = prop.PropertyType.GetElementType();
dynamic list = FastActivator.Create(Type.GetType(string.Format("{0}[[{1},{2}]]", typeof(List<>).FullName, elemType.FullName, elemType.Assembly.GetName())));
foreach (var elem in origCollection)
{
dynamic obj = Clone(elem, flavor, cloneDictionary);
list.Add(obj);
}
cloneCollection = list.ToArray();
}
else
{
cloneCollection = FastActivator.Create(prop.PropertyType);
foreach (var elem in origCollection)
{
dynamic obj = Clone(elem, flavor, cloneDictionary);
cloneCollection.Add(obj);
}
}
prop.SetValue(clone, cloneCollection, null);
continue;
}
try
{
value = prop.GetValue(model, null);
}
catch (Exception)
{
}
if (prop.PropertyType.IsValueType)
{
prop.SetValue(clone, value, null);
}
else
{
var obj = Clone(value, flavor, cloneDictionary);
try
{
prop.SetValue(clone, obj, null);
}
catch (Exception e)
{
throw e;
}
}
}
return clone;
}