/// <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)); } }
/// <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); }