对于一些库调试用途,我正在开发一个自定义属性,它应该能够匹配现有的方法.

例如,以下内容:

[NetMethodAliasMethod("TryParse", Parameters = new Type[] { typeof(string), typeof(char)})]

...应该与静态布尔System.Char.TryParse (string? s, out char result)匹配.根据参数Info.ParameterType MethodInfo.GetParameters()测试属性"PARAMETERS"以匹配参数(当然,名称也匹配).

对于string?,这是可行的,因为可为空的属性不是类型的一部分.但是,对于第二个参数,从MethodInfo返回的类型是char&,而不允许使用typeof(char&).有没有可能通过这种考试?

我在想泛型委托,但没有办法,因为委托的使用是具体说明哪些方法是兼容的.另一个 idea 是使用typeof(System.Char).GetMethod("TryParse").但如果存在多个重载,这会导致相同的问题,我们将不得不使用GetMethods(带‘s’),并再次匹配参数类型.

当然,我可以使用字符串判断类型名称,但如果没有其他方法,这应该是最后的手段.但是既然Type(char&)是存在的,我希望有办法得到它?

推荐答案

您可以使用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();

Csharp相关问答推荐

PredicateBuilder不是循环工作,而是手动工作

CsWin32如何创建PWSTR的实例,例如GetWindowText

如何使用XmlSerializer反序列化字符串数组?

为什么总输出就像12.3没有一分一样?

碰撞检测与盒碰撞器,其isTrigger on问题

使用Audit.EntityFramework,我如何将外键的值设置为相关实体上的属性?

如何使用新的Microsoft.IdentityModel.JsonWebToken创建JwtSecurityToken?

在允许溢出的情况下将小数转换为长

在EF Core中,有没有什么方法可以防止在查询中写入相同的条件,而代之以表达式?

如何在VS代码中为C#DotNet配置.json选项以调试内部终端的控制台应用程序

什么时候接受(等待)信号灯?尽可能的本地化?

如何使用.NET6WPF打印车票?

Lambda表达式如何与隐式强制转换一起工作?

如何防止Visual Studio断点以红色突出显示到整行?

用C#从XML内部元素中获取特定值

{ or ; expected error如何解决此问题

在.NET8中如何反序列化为私有字段?

为什么我的自定义Json.net转换器不工作?

反编译源代码时出现奇怪的字符

使用ImmutableList时,DynamicData未按预期工作