public virtual object Clone()
{
Type t = this.GetType();
// make a copy, attached to broker
SEntity clone = (SEntity)Activator.CreateInstance(t);
// reference all registered fields
IList<FieldInfo> fields = SEntity.GetFieldsOrdered(t);
foreach (FieldInfo field in fields)
{
if (field.FieldType.IsValueType || field.FieldType == typeof(string))
{
// copy over value types
object val = field.GetValue(this);
field.SetValue(clone, val);
}
else if (field.FieldType.IsInterface || typeof(SEntity).IsAssignableFrom(field.FieldType))
{
// make unique copy of referenced type except for owner history!!!
object val = field.GetValue(this);
if (val is SEntity)
{
SEntity sentity = (SEntity)val;
SEntity valclone = (SEntity)sentity.Clone();
field.SetValue(clone, valclone);
}
else
{
field.SetValue(clone, val);
}
}
else if (typeof(IList).IsAssignableFrom(field.FieldType))
{
IList listSource = (IList)field.GetValue(this);
if (listSource != null)
{
// don't copy collections, but initialize new collection
System.Collections.IList listClone = (System.Collections.IList)Activator.CreateInstance(field.FieldType);
field.SetValue(clone, listClone);
Type[] genericargs = field.FieldType.GetGenericArguments();
if (genericargs.Length == 1)
{
foreach (object element in listSource)
{
object elemClone = null;
// clone resources -- don't carry over rooted objects
if (element is ICloneable)
{
// clone resources, list of list, e.g. IfcBSplineSurface
elemClone = ((ICloneable)element).Clone();
}
else
{
// i.e. length coordinate
elemClone = element;
}
// now add to list, INCLUDING IF NULL such as blank entries of table
listClone.Add(elemClone);
}
}
}
}
}
return clone;
}