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!
