public LocalBuilderWrapper DeclareLocal(Type type)
        {
            var local = new LocalBuilderWrapper(type);

            AddInstruction(new ILInstruction(OpCodes.Nop, local, typeof(LocalBuilderWrapper), ILInstructionType.DeclareLocal));
            return(local);
        }
 public void EmitLocal(OpCode opcode, LocalBuilderWrapper local)
 {
     if (opcode == OpCodes.Ldloc || opcode == OpCodes.Stloc || opcode == OpCodes.Ldloca)
     {
         this.AddInstruction(opcode, local);
     }
     else
     {
         throw new Exception("Unsupported Opcode, only Ldloc, Ldloca and Stloc supported");
     }
 }
        public void EmitMemberMap(LocalBuilderWrapper fromLocal, LocalBuilderWrapper toLocal,
                                  MemberMap memberMap, HashSet <Type> convertedTypes)
        {
            var skipMemberMap = this.DefineLabel();

            if (memberMap.FromMember.NeedsContainsCheck)
            {
                var containsKey = fromLocal.LocalType.GetMethod("ContainsKey", new[] { typeof(string) });
                this.EmitLocal(fromLocal.LocalType.IsValueType ? OpCodes.Ldloca : OpCodes.Ldloc, fromLocal);
                this.EmitString(memberMap.FromMember.Name);
                this.EmitCall(OpCodes.Call, containsKey);
                this.EmitBreak(OpCodes.Brfalse, skipMemberMap);
            }

            // Load toLocal as parameter for the setter
            this.EmitLocal(toLocal.LocalType.IsValueType ? OpCodes.Ldloca : OpCodes.Ldloc, toLocal);
            if (memberMap.ToMember.NeedsStringIndex)
            {
                this.EmitString(memberMap.ToMember.Name);
            }

            // Load fromLocal as parameter for the getter
            this.EmitLocal(fromLocal.LocalType.IsValueType ? OpCodes.Ldloca : OpCodes.Ldloc, fromLocal);

            if (memberMap.FromMember.MemberInfo is PropertyInfo)
            {
                var getter = (memberMap.FromMember.MemberInfo as PropertyInfo).GetGetMethod();
                if (memberMap.FromMember.MemberType == MemberType.StringIndexer)
                {
                    this.EmitString(memberMap.FromMember.Name);
                }
                this.EmitCall(OpCodes.Callvirt, getter);
            }
            else if (memberMap.FromMember.MemberInfo is FieldInfo)
            {
                this.EmitField(OpCodes.Ldfld, memberMap.FromMember.MemberInfo as FieldInfo);
            }
            else if (memberMap.FromMember.MemberInfo is MethodInfo)
            {
                var method = memberMap.FromMember.MemberInfo as MethodInfo;
                if (memberMap.FromMember.NeedsStringIndex)
                {
                    this.EmitString(memberMap.FromMember.Name);
                }
                this.EmitCall(OpCodes.Callvirt, method);
            }

            // Convert the value on top of the stack to the correct toType
            this.EmitConvertValue(memberMap.FromMember.Type, memberMap.ToMember.Type, new HashSet <Type>(convertedTypes));

            if (memberMap.ToMember.MemberInfo is PropertyInfo)
            {
                var setter = (memberMap.ToMember.MemberInfo as PropertyInfo).GetSetMethod();
                this.EmitCall(OpCodes.Callvirt, setter);
            }
            else if (memberMap.ToMember.MemberInfo is FieldInfo)
            {
                this.EmitField(OpCodes.Stfld, memberMap.ToMember.MemberInfo as FieldInfo);
            }
            else if (memberMap.ToMember.MemberInfo is MethodInfo)
            {
                this.EmitCall(OpCodes.Call, memberMap.ToMember.MemberInfo as MethodInfo);
            }

            if (memberMap.FromMember.NeedsContainsCheck)
            {
                this.MarkLabel(skipMemberMap);
            }
        }
 private void AddInstruction(OpCode opcode, LocalBuilderWrapper local)
 {
     AddInstruction(new ILInstruction(opcode, local, typeof(LocalBuilderWrapper)));
 }