您可以使用MakeByRefType
方法来制作这样的类型.
然而,您不能在编写属性时实际调用此方法,因为类似typeof(int).MakeByRefType()
的内容不是attribute argument expression(定义在this section的最低端).
因此,我采用的一个解决办法是为您的属性声明一个额外的参数,该参数编码这些"by ref"的位置:
public bool[] ParametersAreByRef { get; set; }
然后执行以下操作:
[NetMethodAliasMethod(
"TryParse",
Parameters = new Type[] { typeof(string), typeof(char)}
ParametersAreByRef = new bool[] { false, true })]
只有在以后检索属性时,才会使用MakeByRefType
根据ParametersAreByRef
中的值重新创建Type
.
var modifiedParameters = attribute.Parameters.Zip(
attribute.ParametersAreByRef, (t, b) => b ? t.MakeByRefType() : t
).ToArray()
如果您不喜欢每次都为带有非引用参数的方法传递ParametersAreByRef
,那么可以将Parameters
设置为位置参数(将其作为构造函数参数),然后可以在构造函数中将默认情况下的ParametersAreByRef
初始化为Parameters.Select(x => false).ToArray()
或类似的值.
正如Jeroen Mostert在注释中建议的那样,另一种解决方法是使用指针类型来编码by-ref-ness,因为它们在实际代码中非常罕见:
Parameters = new Type[] { typeof(string), typeof(char*)}
检索属性实例时,选中IsPointer
并使用GetElementType
:
var modifiedParameters = attribute.Parameters.Select(
x => x.IsPointer ? x.GetElementType().MakeByRefType() : x
).ToArray();
您也可以在Parameters
的setter中这样做,如果它有一个支持字段.
或者,创建您自己的Dummy ByRef<T>
类型,以便可以对By-Ref-ness进行注释:
public abstract class ByRef<T> {}
…
Parameters = new Type[] { typeof(string), typeof(ByRef<char>)}
然后
// e.g. in the setter of Parameters
_parameters = Parameters.Select(
x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(ByRef<>) ? x.GetGenericArguments()[0].MakeByRefType() : x
).ToArray();