Пример #1
0
 public DeepCloneClass(Type type)
 {
     Debug.Assert(!type.IsValueType);
     _type        = type;
     _cloneFields = DeepCloneHelper
                    .GetDeepCloneFields(type)
                    .Select(x => new FieldClone(x))
                    .ToArray();
 }
Пример #2
0
        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);
        }