示例#1
0
    /// <summary>
    /// Create a singleton field used to store property information for the provided property.
    /// </summary>
    /// <param name="property">The property weaver.</param>
    /// <returns></returns>
    public Variable CreatePropertyInfo(PropertyEmitter property)
    {
        var parent = property.Parent.Target.IsNotPublic ? property.Parent : CreateTypeContainer(property.Parent.Target);
        var type   = property.Parent.Target;
        var sta    = (property.Target.GetMethod ?? property.Target.SetMethod).IsStatic;
        var name   = $"<{property.Target.Name}>k__PropertyInfo";

        var existing = parent.GetField(name, Context.Finder.PropertyInfo, toStatic: true);

        if (existing != null)
        {
            return(existing);
        }

        var field = parent.EmitField(name, Context.Finder.PropertyInfo, toStatic: true, toPublic: true);
        var flags = BindingFlags.NonPublic | BindingFlags.Public | (sta ? BindingFlags.Static : BindingFlags.Instance);

        var il = parent.GetStaticConstructor().GetIL();

        il.Emit(Codes.Nop);
        il.Emit(Codes.LoadToken(type.GetGeneric()));
        il.Emit(Codes.InvokeStatic(Context.Finder.TypeGetTypeFromHandle));
        il.Emit(Codes.String(property.Target.Name));
        il.Emit(Codes.Int((int)flags));
        il.Emit(Codes.Invoke(Context.Finder.TypeGetProperty));
        il.Emit(Codes.Store(field));

        return(field);
    }
示例#2
0
    /// <summary>
    /// Create a singleton field used to store parameter information for the provided method.
    /// </summary>
    /// <param name="method">The method weaver.</param>
    /// <param name="param">The parameter.</param>
    /// <returns></returns>
    public Variable CreateParameterInfo(MethodEmitter method, ParameterReference param)
    {
        var parent = method.Parent.Target.IsNotPublic ? method.Parent : CreateTypeContainer(method.Parent.Target);
        var type   = method.Parent.Target;

        var id   = method.Target.GetHashString();
        var name = $"<{method.Target.Name}${id}${param.Index}>k__ParameterInfo";

        var existing = parent.GetField(name, Context.Finder.ParameterInfo, toStatic: true);

        if (existing != null)
        {
            return(existing);
        }

        var field = parent.EmitField(name, Context.Finder.ParameterInfo, toStatic: true, toPublic: true);

        var il = parent.GetStaticConstructor().GetIL();

        il.Emit(Codes.Nop);
        il.Emit(Codes.LoadToken(type.HasGenericParameters ? method.Target : method.Target.GetGeneric()));
        il.Emit(Codes.LoadToken(type.GetGeneric()));
        il.Emit(Codes.InvokeStatic(Context.Finder.MethodBaseGetMethodFromHandleAndType));
        il.Emit(Codes.Invoke(Context.Finder.MethodBaseGetParameters));
        il.Emit(Codes.Int(param.Index));
        il.Emit(Codes.LoadArray);
        il.Emit(Codes.Store(field));

        return(field);
    }
示例#3
0
    /// <summary>
    /// Copies the values of an array of parameter values into the corresponding parameters.
    /// </summary>
    /// <param name="method">The method.</param>
    /// <param name="array">The array.</param>
    public void CopyArgumentArrayToParameters(MethodEmitter method, Variable array)
    {
        var parameters = method.Target.Parameters;
        var count      = parameters.Count;

        var il = method.GetIL();

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

            if (type.IsByReference || p.IsOut)
            {
                continue;
            }

            il.Emit(Codes.Load(array));
            il.Emit(Codes.Int(i));
            il.Emit(Codes.LoadArray);
            il.Emit(Codes.Unbox(type));
            il.Emit(Codes.Store(variable));
        }

        CopyArgumentArrayToReferences(method, array);
    }
示例#4
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));
        }
    }
示例#5
0
    /// <summary>
    /// Copies the values of an array of parameter values into the required references.
    /// </summary>
    /// <param name="method">The method.</param>
    /// <param name="array">The array.</param>
    public void CopyArgumentArrayToReferences(MethodEmitter method, Variable array)
    {
        var parameters = method.Target.Parameters;
        var count      = parameters.Count;

        var il = method.GetIL();

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

            if (!type.IsByReference || p.IsOut)
            {
                continue;
            }

            var spec     = (TypeSpecification)type;
            var unboxing = true;

            il.Emit(Codes.Arg(p));
            il.Emit(Codes.Load(array));
            il.Emit(Codes.Int(i));
            il.Emit(Codes.LoadArray);

            var code = OpCodes.Nop;

            switch (spec.ElementType.MetadataType)
            {
            case MetadataType.Boolean:
            case MetadataType.SByte:
            case MetadataType.Byte:
                code = OpCodes.Stind_I1;
                break;

            case MetadataType.Int16:
            case MetadataType.UInt16:
                code = OpCodes.Stind_I2;
                break;

            case MetadataType.Int32:
            case MetadataType.UInt32:
                code = OpCodes.Stind_I4;
                break;

            case MetadataType.Int64:
            case MetadataType.UInt64:
                code = OpCodes.Stind_I8;
                break;

            case MetadataType.Single:
                code = OpCodes.Stind_R4;
                break;

            case MetadataType.Double:
                code = OpCodes.Stind_R8;
                break;

            case MetadataType.IntPtr:
            case MetadataType.UIntPtr:
                code = OpCodes.Stind_I;
                break;

            default:
                if (spec.ElementType.IsValueType)
                {
                    il.Emit(Instruction.Create(OpCodes.Stobj, spec.ElementType));
                }
                else
                {
                    code     = OpCodes.Stind_Ref;
                    unboxing = false;
                }
                break;
            }

            if (unboxing)
            {
                il.Emit(Codes.Unbox(spec.ElementType));
            }

            if (code != OpCodes.Nop)
            {
                il.Emit(code);
            }
        }
    }
示例#6
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);
    }