コード例 #1
0
        private IList <Instruction> LoadValueOnStack(TypeReference parameterType, object value)
        {
            if (parameterType.IsArray(out var elementType) && value is CustomAttributeArgument[] args)
            {
                elementType   = elementType.CleanEnumsInTypeRef();
                parameterType = parameterType.CleanEnumsInTypeRef();

                var array = CreateVariable(parameterType);
                var createArrayInstructions = new List <Instruction>()
                {
                    _processor.Create(OpCodes.Ldc_I4, args.Length),
                    _processor.Create(OpCodes.Newarr, elementType),
                    _processor.Create(OpCodes.Stloc, array)
                };

                var stelem = elementType.GetStElemCode();

                for (var i = 0; i < args.Length; ++i)
                {
                    var parameter = args[i];
                    createArrayInstructions.Add(_processor.Create(OpCodes.Ldloc, array));
                    createArrayInstructions.Add(_processor.Create(OpCodes.Ldc_I4, i));
                    createArrayInstructions.AddRange(LoadValueOnStack(elementType, parameter.Value));
                    createArrayInstructions.Add(_processor.Create(stelem));
                }

                createArrayInstructions.Add(_processor.Create(OpCodes.Ldloc, array));
                return(createArrayInstructions);
            }

            if (parameterType.IsEnum(out var enumUnderlyingType))
            {
                enumUnderlyingType = enumUnderlyingType.CleanEnumsInTypeRef();
                return(new List <Instruction>(LoadPrimitiveConstOnStack(enumUnderlyingType.MetadataType, value)));
            }

            if (parameterType.IsPrimitive || (parameterType.FullName == typeof(String).FullName))
            {
                return(new List <Instruction>(LoadPrimitiveConstOnStack(parameterType.MetadataType, value)));
            }

            if (parameterType.FullName == typeof(Type).FullName)
            {
                var typeVal       = (TypeReference)value;
                var typeReference = typeVal.CleanEnumsInTypeRef();

                var typeTypeRef     = _referenceFinder.GetTypeReference(typeof(Type));
                var methodReference = _referenceFinder.GetMethodReference(typeTypeRef, md => md.Name == nameof(Type.GetTypeFromHandle));

                var instructions = new List <Instruction>
                {
                    _processor.Create(OpCodes.Ldtoken, typeReference),
                    _processor.Create(OpCodes.Call, methodReference)
                };

                return(instructions);
            }

            if (parameterType.FullName == typeof(Object).FullName && value is CustomAttributeArgument arg)
            {
                var valueType = arg.Type;
                if (arg.Value is TypeReference)
                {
                    valueType = _referenceFinder.GetTypeReference(typeof(Type));
                }
                var isEnum = valueType.IsEnum(out _);
                valueType = valueType.CleanEnumsInTypeRef();
                var instructions = LoadValueOnStack(valueType, arg.Value);
                if (valueType.IsValueType || (!valueType.IsArray && isEnum))
                {
                    instructions.Add(_processor.Create(OpCodes.Box, valueType));
                }
                return(instructions);
            }

            throw new NotSupportedException("Parametertype: " + parameterType);
        }