コード例 #1
0
    /// <summary>
    /// Creates a reference to a parameter used in a custom attribute.
    /// </summary>
    /// <param name="emitter">The emitter.</param>
    /// <param name="attribute">The attribute.</param>
    /// <param name="arg">The argument.</param>
    public void CreateAttributeParameter(MethodEmitter emitter, CustomAttribute attribute, CustomAttributeArgument arg)
    {
        var il = emitter.GetIL();

        if (arg.Value == null)
        {
            il.Emit(Codes.Null);
            return;
        }

        var type = arg.Type;

        if (type.IsArray)
        {
            var elements = (arg.Value as IEnumerable).Cast <CustomAttributeArgument>().ToArray();

            il.Emit(Codes.Int(elements.Length));
            il.Emit(Codes.CreateArray(type.GetElementType()));

            if (elements.Length == 0)
            {
                return;
            }

            il.Emit(Codes.Duplicate);

            for (int i = 0, count = elements.Length; i < count; i++)
            {
                il.Emit(Codes.Int(i));

                if (elements[i].Value == null)
                {
                    il.Emit(Codes.Null);
                    il.Emit(Codes.StoreArray);
                }
                else
                {
                    il.Emit(Codes.Load(elements[i].Value));
                    il.Emit(Codes.StoreArray);
                }

                if (i + 1 < count)
                {
                    il.Emit(Codes.Duplicate);
                }
            }
        }
        else
        {
            il.Emit(Codes.Load(arg.Value));
        }
    }
コード例 #2
0
    /// <summary>
    /// Create an array variable containing the arguments of the method invocation.
    /// </summary>
    /// <param name="method">The method weaver.</param>
    /// <returns></returns>
    public Variable CreateArgumentArray(MethodEmitter method)
    {
        var parameters = method.Target.Parameters;
        var count      = parameters.Count;

        var array = method.EmitLocal(Context.Finder.ObjectArray);
        var il    = method.GetIL();

        il.Emit(Codes.Nop);
        il.Emit(Codes.Int(count));
        il.Emit(Codes.CreateArray(TypeSystem.ObjectReference));
        il.Emit(Codes.Store(array));

        for (int i = 0; i < count; i++)
        {
            var p    = parameters[i];
            var type = p.ParameterType;

            il.Emit(Codes.Load(array));
            il.Emit(Codes.Int(i));

            if (p.IsOut)
            {
                var spec = (TypeSpecification)type;

                if (spec.ElementType.IsValueType)
                {
                    il.Emit(Codes.Init(spec.ElementType));
                }
                else
                {
                    il.Emit(Codes.Null);
                    il.Emit(Codes.StoreArray);
                }

                continue;
            }

            il.Emit(Codes.Arg(p));

            if (type.IsByReference)
            {
                var spec   = (TypeSpecification)type;
                var boxing = true;

                switch (spec.ElementType.MetadataType)
                {
                case MetadataType.SByte:
                    il.Emit(OpCodes.Ldind_I1);
                    break;

                case MetadataType.Int16:
                    il.Emit(OpCodes.Ldind_I2);
                    break;

                case MetadataType.Int32:
                    il.Emit(OpCodes.Ldind_I4);
                    break;

                case MetadataType.Int64:
                case MetadataType.UInt64:
                    il.Emit(OpCodes.Ldind_I8);
                    break;

                case MetadataType.Boolean:
                case MetadataType.Byte:
                    il.Emit(OpCodes.Ldind_U1);
                    break;

                case MetadataType.UInt16:
                    il.Emit(OpCodes.Ldind_U2);
                    break;

                case MetadataType.UInt32:
                    il.Emit(OpCodes.Ldind_U4);
                    break;

                case MetadataType.Single:
                    il.Emit(OpCodes.Ldind_R4);
                    break;

                case MetadataType.Double:
                    il.Emit(OpCodes.Ldind_R8);
                    break;

                case MetadataType.IntPtr:
                case MetadataType.UIntPtr:
                    il.Emit(OpCodes.Ldind_I);
                    break;

                default:
                    if (spec.ElementType.IsValueType)
                    {
                        il.Emit(Instruction.Create(OpCodes.Ldobj, spec.ElementType));
                    }
                    else
                    {
                        il.Emit(OpCodes.Ldind_Ref);
                        boxing = false;
                    }
                    break;
                }

                if (boxing)
                {
                    il.Emit(Codes.Box(spec.ElementType));
                }
            }
            else
            {
                il.Emit(Codes.Box(p.ParameterType));
            }

            il.Emit(Codes.StoreArray);
        }

        return(array);
    }