使用 ParameterBuilder 将自定义属性添加到 return 值;反射时属性不显示——为什么?

Adding a custom attribute to a return value using a ParameterBuilder; attribute doesn't show when reflected -- why?

我觉得我的问题标题有点混乱,所以让我澄清一下。出于我的目的,我将 MarshalAsAttribute 应用于参数和 return 类型。

(注意:最初我认为这根本不起作用,但这里的这个问题让我想到 post 这个问题:System.Reflection.Emit - How to add attribute to return type definition?

假设我正在为具有此签名的方法动态创建委托类型:

[return: MarshalAs(UnmanagedType.I1)]
internal static extern Boolean SomeFunction([MarshalAs(UnmanagedType.LPStr)] string argument);

使用类似于以下的代码,我可以很好地处理函数参数和 return 类型(请注意,为简洁起见,我在这里省略了一堆):

var currentParameterAttributeBuilder = methodBuilder.DefineParameter(parameterPosition, currentParameterAttributes,
                    parameterName);
var attributeParams = new Type[] { typeof(UnmanagedType) };
var attributeConstructorInfo = typeof(MarshalAsAttribute).GetConstructor(attributeParams);
var customParameterAttribute = new CustomAttributeBuilder(attributeConstructorInfo, new object[] { currentArgument.MarshallingType });
currentParameterAttributeBuilder.SetCustomAttribute(customParameterAttribute);

但是,当我通过反射检查属性是否存在时,如下所示:

// This works and retrieves the MarshalAs attribute, 'param' being a parameter retrieved from a foreach iteration over type.GetMethod("Invoke").GetParameters()
var argumentCustomAttributes = param.GetCustomAttributes(typeof(MarshalAsAttribute), false);
// This doesn't work; it doesn't 'see' the MarshalAs attribute 
var returnCustomAttributes = type.GetMethod("Invoke").ReturnType.GetCustomAttributes(typeof(MarshalAsAttribute), false);

所以基本上,return 类型的属性无法通过反射查看,但实际上已应用,如 .NET Reflector 屏幕截图所示(此签名与上面不同,但展示了我的点):

example image <-- 我没有足够的声誉来嵌入图像,抱歉。

我很好奇是否有人知道这是为什么,因为在我偶然发现另一个 post 并意识到它实际上被正确应用之前,我花了相当多的时间来研究它。希望我的格式正确;这是我第一次 posting.

看来我应该多加注意,因为我使用了错误的 MethodInfo 属性。

而不是 MethodInfo 的 "ReturnType",我应该使用 "ReturnParameter",或者对于这种特定情况,"ReturnTypeCustomAttributes" —— 两者都可以用于此目的。 "ReturnParameter" 特别提到自定义修饰符。糟糕!

var returnCustomAttributes = type.GetMethod("Invoke").ReturnParameter.GetCustomAttributes(typeof(MarshalAsAttribute), false);