using System;
using System.IO;
using System.Reflection;
using System.Diagnostics;
using System.Globalization;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
public class Test
{
[Serializable]
public class DataItem
{
public Int32 Property1 { get; set; }
public String Property2 { get; set; }
public Int32 Property3 { get; set; }
}
public static void Main()
{
DataItem[] items = CreateTestData(Int32.Parse(Console.ReadLine()));
Measure("Serialize",
delegate
{
DataItem[] items2 = Clone(items);
});
Measure("Reflection",
delegate
{
DataItem[] items3 = CopyProperties<DataItem, DataItem>(items);
});
}
static DataItem[] CreateTestData(Int32 count)
{
Random rnd = new Random();
DataItem[] result = new DataItem[count];
for(Int32 loop = 0; loop < count; loop++)
{
result[loop] = new DataItem();
result[loop].Property1 = rnd.Next();
result[loop].Property2 = rnd.Next().ToString();
result[loop].Property3 = rnd.Next();
}
return result;
}
static T Clone<T>(T target)
{
using(MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, target);
stream.Position = 0;
T result = (T)formatter.Deserialize(stream);
return result;
}
}
static void CopyProperties<S, T>(S source, T target) where T : class
{
Type type = typeof(T);
PropertyInfo[] properties = source.GetType().GetProperties();
foreach(PropertyInfo property in properties)
{
PropertyInfo targetProperty = type.GetProperty(property.Name);
if(targetProperty != null)
targetProperty.SetValue(target, property.GetValue(source, null), null);
}
}
static T[] CopyProperties<S, T>(S[] source) where T : class, new()
{
if(source == null)
throw new ArgumentNullException("source");
T[] result = new T[source.Length];
for(Int32 loop = 0; loop < source.Length; loop++)
{
result[loop] = new T();
CopyProperties(source[loop], result[loop]);
}
return result;
}
static void Measure(String message, Action method)
{
Int64 mem = GC.GetTotalMemory(true);
Int64 gcCount = GC.CollectionCount(0);
DateTime now = DateTime.Now;
Stopwatch stopwatch = Stopwatch.StartNew();
method();
TimeSpan elapsed = stopwatch.Elapsed;
// DONTTOUCH:
// It is intended to call GetTotalMemory with forceFullCollection: false
// before CollectionCount call.
Double tempMemDelta = Math.Max(GC.GetTotalMemory(false) - mem, 0);
Int64 gcCountDelta = GC.CollectionCount(0) - gcCount;
String elapsedString = elapsed.TotalSeconds.ToString("00.0000", CultureInfo.InvariantCulture);
String memDeltaInKb = (tempMemDelta / 1024).ToString("0.00 KB", CultureInfo.InvariantCulture);
Console.WriteLine(@"{0}:
Elapsed: {1} s, MemDelta: {2,10}, GC count: {3}
", message, elapsedString, memDeltaInKb, gcCountDelta);
}
}