4 using System.Collections.Generic;
5 using System.Reflection.Emit;
6 using System.Reflection;
8 namespace SiliconStudio.Presentation.Extensions
12 private static readonly Dictionary<Type, Delegate> CachedMemberwiseCloneMethods =
new Dictionary<Type, Delegate>();
23 public static T SafeArgument<T>(
this T obj,
string argumentName) where T :
class
25 if (argumentName == null)
throw new ArgumentNullException(
"argumentName");
26 if (obj == null)
throw new ArgumentNullException(argumentName);
33 throw new ArgumentNullException(
"instance");
37 Type instanceType = instance.GetType();
39 if (CachedMemberwiseCloneMethods.TryGetValue(instanceType, out method) ==
false)
41 DynamicMethod dynamicMethod = GenerateDynamicMethod(instanceType);
43 Type methodType = typeof(Func<,>).MakeGenericType(instanceType, instanceType);
44 method = dynamicMethod.CreateDelegate(methodType);
46 CachedMemberwiseCloneMethods.Add(instanceType, method);
49 return method.DynamicInvoke(instance);
52 public static T MemberwiseClone<T>(
this T instance)
55 throw new ArgumentNullException(
"instance");
57 Delegate method = null;
59 Type instanceType = typeof(T);
61 if (CachedMemberwiseCloneMethods.TryGetValue(instanceType, out method) ==
false)
63 DynamicMethod dynamicMethod = GenerateDynamicMethod(instanceType);
65 method = dynamicMethod.CreateDelegate(typeof(Func<T, T>));
67 CachedMemberwiseCloneMethods.Add(typeof(T), method);
70 return ((Func<T, T>)method)(instance);
73 private static DynamicMethod GenerateDynamicMethod(Type instanceType)
75 DynamicMethod dymMethod =
new DynamicMethod(
"DynamicCloneMethod", instanceType,
new Type[] { instanceType },
true);
77 ILGenerator generator = dymMethod.GetILGenerator();
79 generator.DeclareLocal(instanceType);
81 bool isValueType = instanceType.IsValueType;
85 generator.Emit(OpCodes.Ldloca, 0);
86 generator.Emit(OpCodes.Initobj, instanceType);
90 ConstructorInfo constructorInfo = instanceType.GetConstructor(
new Type[0]);
91 generator.Emit(OpCodes.Newobj, constructorInfo);
92 generator.Emit(OpCodes.Stloc_0);
95 foreach (FieldInfo field
in instanceType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
99 generator.Emit(OpCodes.Ldloca, 0);
101 generator.Emit(OpCodes.Ldloc_0);
103 generator.Emit(OpCodes.Ldarg_0);
105 generator.Emit(OpCodes.Ldfld, field);
108 generator.Emit(OpCodes.Stfld, field);
112 generator.Emit(OpCodes.Ldloc_0);
114 generator.Emit(OpCodes.Ret);
static object MemberwiseClone(this object instance)