My next step is making CodeRush shortcuts for these classes but meanwhile I decided to have them here so I can refer quickly to them.
Update:
This is exactly the type of post that I always find and then I have to look into the source code to get the code I need.
https://www.devexpress.com/Support/Center/Question/Details/T825872/how-to-clone-an-object-example
I wish we had something like https://source.xafmarin.com for XAF.
XpoHelper.cs
public static class XpoHelper { static readonly Type[] EntityTypes = new Type[] { typeof(Item) }; public static void InitXpo(string connectionString) { var dictionary = PrepareDictionary(); if (XpoDefault.DataLayer == null) { using (var updateDataLayer = XpoDefault.GetDataLayer(connectionString, dictionary, AutoCreateOption.DatabaseAndSchema)) { updateDataLayer.UpdateSchema(false, dictionary.CollectClassInfos(EntityTypes)); new UnitOfWork(updateDataLayer).CreateObjectTypeRecords(); } } var dataStore = XpoDefault.GetConnectionProvider(connectionString, AutoCreateOption.SchemaAlreadyExists); XpoDefault.DataLayer = new ThreadSafeDataLayer(dictionary, dataStore); XpoDefault.Session = null; } public static UnitOfWork CreateUnitOfWork() { return new UnitOfWork(); } static XPDictionary PrepareDictionary() { var dict = new ReflectionDictionary(); dict.GetDataStoreSchema(EntityTypes); return dict; } }
CloneHelper.cs
public class CloneHelper : IDisposable { readonly Dictionary<object, object> clonedObjects; readonly Session targetSession; public CloneHelper(Session targetSession) { clonedObjects = new Dictionary<object, object>(); this.targetSession = targetSession; } public T Clone<T>(T source) { return Clone<T>(source, false); } public T Clone<T>(T source, bool synchronize) { return (T)Clone((object)source, synchronize); } public object Clone(object source) { return Clone(source, false); } /// <param name="synchronize">If set to true, reference properties are only cloned in case /// the reference object does not exist in the targetsession. Otherwise the exising object will be /// reused and synchronized with the source. Set this property to false when knowing at forehand /// that the targetSession will not contain any of the objects of the source.</param> /// <returns></returns> public object Clone(object source, bool synchronize) { if (source == null) return null; XPClassInfo targetClassInfo = targetSession.GetClassInfo(source.GetType()); object target = targetClassInfo.CreateNewObject(targetSession); clonedObjects.Add(source, target); foreach (XPMemberInfo m in targetClassInfo.PersistentProperties) { CloneProperty(m, source, target, synchronize); } foreach (XPMemberInfo m in targetClassInfo.CollectionProperties) { CloneCollection(m, source, target, synchronize); } return target; } private void CloneProperty(XPMemberInfo memberInfo, object source, object target, bool synchronize) { if (memberInfo is DevExpress.Xpo.Metadata.Helpers.ServiceField || memberInfo.IsKey) { return; } object clonedValue = null; if (memberInfo.ReferenceType != null) { object value = memberInfo.GetValue(source); if (value != null) { clonedValue = CloneValue(value, synchronize, false); } } else { clonedValue = memberInfo.GetValue(source); } memberInfo.SetValue(target, clonedValue); } private void CloneCollection(XPMemberInfo memberInfo, object source, object target, bool synchronize) { if (memberInfo.IsAssociation && (memberInfo.IsManyToMany || memberInfo.IsAggregated)) { XPBaseCollection colTarget = (XPBaseCollection)memberInfo.GetValue(target); XPBaseCollection colSource = (XPBaseCollection)memberInfo.GetValue(source); foreach (IXPSimpleObject obj in colSource) { colTarget.BaseAdd(CloneValue(obj, synchronize, !memberInfo.IsManyToMany)); } } } private object CloneValue(object propertyValue, bool synchronize, bool cloneAlways) { if (clonedObjects.ContainsKey(propertyValue)) { return clonedObjects[propertyValue]; } object clonedValue = null; if (synchronize && !cloneAlways) { clonedValue = targetSession.GetObjectByKey(targetSession.GetClassInfo(propertyValue), targetSession.GetKeyValue(propertyValue)); } if (clonedValue == null) { clonedValue = Clone(propertyValue, synchronize); } return clonedValue; } public void Dispose() { if (targetSession != null) targetSession.Dispose(); } }
ConnectionHelper.cs
public static class ConnectionHelper { static Type[] persistentTypes = new Type[] { }; public static void Connect(DevExpress.Xpo.DB.AutoCreateOption autoCreateOption, bool threadSafe = false) { if (threadSafe) { var provider = XpoDefault.GetConnectionProvider(ConnectionString, autoCreateOption); var dictionary = new ReflectionDictionary(); dictionary.GetDataStoreSchema(persistentTypes); XpoDefault.DataLayer = new ThreadSafeDataLayer(dictionary, provider); } else { XpoDefault.DataLayer = XpoDefault.GetDataLayer(ConnectionString, autoCreateOption); } XpoDefault.Session = null; } public static DevExpress.Xpo.DB.IDataStore GetConnectionProvider(DevExpress.Xpo.DB.AutoCreateOption autoCreateOption) { return XpoDefault.GetConnectionProvider(ConnectionString, autoCreateOption); } public static DevExpress.Xpo.DB.IDataStore GetConnectionProvider(DevExpress.Xpo.DB.AutoCreateOption autoCreateOption, out IDisposable[] objectsToDisposeOnDisconnect) { return XpoDefault.GetConnectionProvider(ConnectionString, autoCreateOption, out objectsToDisposeOnDisconnect); } public static IDataLayer GetDataLayer(DevExpress.Xpo.DB.AutoCreateOption autoCreateOption) { return XpoDefault.GetDataLayer(ConnectionString, autoCreateOption); } public static Type[] GetPersistentTypes() { Type[] copy = new Type[persistentTypes.Length]; Array.Copy(persistentTypes, copy, persistentTypes.Length); return copy; } public static string ConnectionString { get { return System.Configuration.ConfigurationManager.ConnectionStrings["TaskManager"].ConnectionString; } } }
Simpler ConnectionHelper
public static class ConnectionHelper { static readonly Type[] PersistentTypes = new Type[]{ typeof(Order), typeof(Customer) }; public static void Connect(bool threadSafe = true) { XpoDefault.DataLayer = CreateDataLayer(threadSafe); } static IDataLayer CreateDataLayer(bool threadSafe) { string connStr = ConfigurationManager.ConnectionStrings["XpoTutorial"].ConnectionString; //connStr = XpoDefault.GetConnectionPoolString(connStr); // Uncomment this line if you use a database server like SQL Server, Oracle, PostgreSql etc. ReflectionDictionary dictionary = new ReflectionDictionary(); dictionary.GetDataStoreSchema(PersistentTypes); // Pass all of your persistent object types to this method. AutoCreateOption autoCreateOption = AutoCreateOption.DatabaseAndSchema; // Use AutoCreateOption.DatabaseAndSchema if the database or tables do not exist. Use AutoCreateOption.SchemaAlreadyExists if the database already exists. IDataStore provider = XpoDefault.GetConnectionProvider(connStr, autoCreateOption); return threadSafe ? (IDataLayer)new ThreadSafeDataLayer(dictionary, provider) : new SimpleDataLayer(dictionary, provider); } }
Bonus:
public static byte[] ToByteArray<T>(T Data) { try { var StatementType = typeof(T); var fs = new MemoryStream(); using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(fs)) { XmlSerializer serializer = new XmlSerializer(StatementType); serializer.Serialize(writer, Data); } if (System.Diagnostics.Debugger.IsAttached) { //HACK only for debug how much data are we sending var array = fs.ToArray(); Debug.WriteLine(string.Format("{0}:{1} kb", "Length before compression", Convert.ToDecimal(array.Length) / Convert.ToDecimal(1000))); array = Compress(array); Debug.WriteLine(string.Format("{0}:{1} kb", "Length after compression", Convert.ToDecimal(array.Length) / Convert.ToDecimal(1000))); return array; } return Compress(fs.ToArray()); } catch (Exception exception) { Debug.WriteLine(string.Format("{0}:{1}", "exception.Message", exception.Message)); if (exception.InnerException != null) { Debug.WriteLine(string.Format("{0}:{1}", "exception.InnerException.Message", exception.InnerException.Message)); } Debug.WriteLine(string.Format("{0}:{1}", " exception.StackTrace", exception.StackTrace)); } return null; }
public static T GetObjectsFromByteArray<T>(byte[] bytes) { var Type = typeof(T);//OperationsAssmbly.GetType(ObjectType); using (MemoryStream fs = new MemoryStream(bytes)) using (var gZipStream = new GZipStream(fs, CompressionMode.Decompress)) { using (XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(gZipStream, XmlDictionaryReaderQuotas.Max)) { XmlSerializer serializer = new XmlSerializer(Type); var Statement = (T)Convert.ChangeType(serializer.Deserialize(reader), Type); return Statement; } } }
private static byte[] Compress(byte[] raw) { using (MemoryStream memory = new MemoryStream()) { using (GZipStream gzip = new GZipStream(memory, CompressionMode.Compress, true)) { gzip.Write(raw, 0, raw.Length); } return memory.ToArray(); } }
Helpers out!