public DeepCloneClass(Type type) { Debug.Assert(!type.IsValueType); _type = type; _cloneFields = DeepCloneHelper .GetDeepCloneFields(type) .Select(x => new FieldClone(x)) .ToArray(); }
private static void EmitClone(this ILGenerator il, Type type) { var fields = DeepCloneHelper .GetDeepCloneFields(type) .ToArray(); if (fields.Length == 0) { // nothing to clone il.EmitCreateObject(type); return; } var src = il.DeclareLocal(type).LocalIndex; var dest = il.DeclareLocal(type).LocalIndex; // src = (type)p_1; il.EmitLdarg(1); il.EmitUnBoxAnyOrCastClass(type); il.EmitStloc(src); // dest = (type)CreateObject(type); il.EmitCreateObject(type); il.EmitUnBoxAnyOrCastClass(type); il.EmitStloc(dest); foreach (var field in fields) { Debug.Assert(field.CloneType != CloneType.Ignore); var fieldInfo = field.Field; if (type.IsValueType) { il.EmitLdloca(dest); } else { il.EmitLdloc(dest); } if (field.CloneType == CloneType.Deep) { // ctx il.EmitLdarg(0); // (object)src.Field il.EmitLdloc(src); il.EmitFieldGet(fieldInfo); il.EmitBox(fieldInfo.FieldType); // ctx.Clone() il.EmitMethodCall(_ctxClone); // (object) il.EmitUnBoxAnyOrCastClass(fieldInfo.FieldType); } else { il.EmitLdloc(src); il.EmitFieldGet(fieldInfo); } // [dest].Field= il.EmitFieldSet(fieldInfo); } il.EmitLdloc(dest); il.EmitBox(type); }