|
using System; |
|
using System.Collections.Concurrent; |
|
using System.Diagnostics; |
|
using System.Linq; |
|
using System.Reflection; |
|
using System.Reflection.Emit; |
|
|
|
namespace DynamicTest |
|
{ |
|
class Program |
|
{ |
|
static void Main(string[] args) |
|
{ |
|
|
|
var typeNames = Enumerable |
|
.Repeat(new[] { "DynamicTest.Program+Customer,DynamicTest", "DynamicTest.Program+Supplier,DynamicTest", "DynamicTest.Program+Contact,DynamicTest" }, 1000000) |
|
.SelectMany(name => name) |
|
.ToArray(); |
|
|
|
Console.WriteLine("Creating objects using IL/Dynamic"); |
|
|
|
var sw = Stopwatch.StartNew(); |
|
|
|
foreach (var typeName in typeNames) |
|
{ |
|
DynamicObjectActivator create = TypeConstructorCache.GetOrAdd( |
|
typeName, |
|
key => CreateCtor(Type.GetType(typeName)) |
|
); |
|
|
|
var myObj = create(); |
|
switch(myObj) |
|
{ |
|
case Customer customer: |
|
{ |
|
// got an customer |
|
// do stuff |
|
} |
|
break; |
|
case Supplier supplier: |
|
{ |
|
// got an supplier |
|
// do stuff |
|
} |
|
break; |
|
case Contact contact: |
|
{ |
|
// got an contact |
|
// do stuff |
|
} |
|
break; |
|
} |
|
} |
|
|
|
sw.Stop(); |
|
|
|
Console.WriteLine($"Created {typeNames.Length} in {sw.Elapsed}"); |
|
|
|
Console.WriteLine("Creating objects using un cached Activator.CreateInstance"); |
|
|
|
var sw2 = Stopwatch.StartNew(); |
|
|
|
foreach (var typeName in typeNames) |
|
{ |
|
|
|
|
|
var myObj = Activator.CreateInstance(Type.GetType(typeName)); ; |
|
switch (myObj) |
|
{ |
|
case Customer customer: |
|
{ |
|
// got an customer |
|
// do stuff |
|
} |
|
break; |
|
case Supplier supplier: |
|
{ |
|
// got an supplier |
|
// do stuff |
|
} |
|
break; |
|
case Contact contact: |
|
{ |
|
// got an contact |
|
// do stuff |
|
} |
|
break; |
|
} |
|
} |
|
|
|
sw2.Stop(); |
|
|
|
Console.WriteLine($"Created {typeNames.Length} in {sw2.Elapsed}"); |
|
} |
|
|
|
public class Customer |
|
{ } |
|
|
|
public class Supplier |
|
{ } |
|
|
|
public class Contact |
|
{ } |
|
|
|
|
|
public static ConcurrentDictionary<string, DynamicObjectActivator> GenericTypeConstructorCache = new ConcurrentDictionary<string, DynamicObjectActivator>(); |
|
public static ConcurrentDictionary<string, DynamicObjectActivator> TypeConstructorCache = new ConcurrentDictionary<string, DynamicObjectActivator>(); |
|
|
|
public static object StopWatch { get; private set; } |
|
|
|
public static DynamicObjectActivator<T> CreateCtor<T>() |
|
{ |
|
var type = typeof(T); |
|
ConstructorInfo emptyConstructor = type.GetConstructor(Type.EmptyTypes); |
|
var dynamicMethod = new DynamicMethod("CreateInstance", type, Type.EmptyTypes, true); |
|
ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); |
|
ilGenerator.Emit(OpCodes.Nop); |
|
ilGenerator.Emit(OpCodes.Newobj, emptyConstructor); |
|
ilGenerator.Emit(OpCodes.Ret); |
|
return (DynamicObjectActivator<T>)dynamicMethod.CreateDelegate(typeof(DynamicObjectActivator<T>)); |
|
} |
|
|
|
public static DynamicObjectActivator CreateCtor(Type type) |
|
{ |
|
if (type == null) |
|
{ |
|
throw new NullReferenceException("type"); |
|
} |
|
ConstructorInfo emptyConstructor = type.GetConstructor(Type.EmptyTypes); |
|
var dynamicMethod = new DynamicMethod("CreateInstance", type, Type.EmptyTypes, true); |
|
ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); |
|
ilGenerator.Emit(OpCodes.Nop); |
|
ilGenerator.Emit(OpCodes.Newobj, emptyConstructor); |
|
ilGenerator.Emit(OpCodes.Ret); |
|
return (DynamicObjectActivator)dynamicMethod.CreateDelegate(typeof(DynamicObjectActivator)); |
|
} |
|
|
|
public delegate T DynamicObjectActivator<T>(); |
|
public delegate object DynamicObjectActivator(); |
|
} |
|
} |