.net 如何将属性的PropertyInfo作为属性中的参数传递?
假设我有两门课:.net 如何将属性的PropertyInfo作为属性中的参数传递?,.net,reflection,lambda,.net,Reflection,Lambda,假设我有两门课: class A { [SortOrder(3)] public string Name { get; set; } } class B : A { [SortBefore(*****)] public string Age { get; set; } } 请注意第二个类中property属性中的星号。在SortBefore属性中指定一个.Name(我想使用表达式)是否可能?请注意,我不是在A的实例中查找Name的值,而是在A中查找属性名称的Prope
class A
{
[SortOrder(3)]
public string Name { get; set; }
}
class B : A
{
[SortBefore(*****)]
public string Age { get; set; }
}
请注意第二个类中property属性中的星号。在SortBefore属性中指定一个.Name(我想使用表达式)是否可能?请注意,我不是在A的实例中查找Name的值,而是在A中查找属性名称的PropertyInfo,以便在B中使用Age的PropertyInfo时,可以从其超类中检索SortOrder值。恐怕您不能。这可能在IL中实现——我不确定——但在C#中实现不了
最接近你的可能是:
[排序在(A),“名称”之前]
并获取属性以在执行时查找属性。是的,这是非常脆弱的-如果你这样做,我会添加一个单元测试,它会找到程序集中的所有属性并检查它们是否都有效。恐怕你不能。这可能在IL中实现——我不确定——但在C#中实现不了
最接近你的可能是:
[排序在(A),“名称”之前]
并获取属性以在执行时查找属性。是的,这是非常脆弱的-如果你这样做,我会添加一个单元测试,它会找到程序集中的所有属性并检查它们是否都有效。甚至C#typeof
操作符也由编译器作为ldtoken
实现,然后调用Type.GetTypeFromHandle()
。PropertyInfo
是一个特别有趣的例子,因为ldtoken
IL指令不能将属性元数据标记作为参数,并且没有RuntimePropertyHandle类型。但是,可以在IL via中获得getter和/或setter方法(这不是有效的IL,但显示了说明)。不幸的是,在C#中没有直接的方法来生成具有typeof()
操作符提供的类型安全级别的代码
ldtoken <method>
call MethodBase.GetMethodFromHandle
ldtoken
调用MethodBase.GetMethodFromHandle
的答案显示了如何从MethodInfo获取PropertyInfo
Jon关于您可能必须使用的解决方案的回答是正确的。即使是C#typeof
操作符也由编译器实现为ldtoken
,然后调用Type.GetTypeFromHandle()
。PropertyInfo
是一个特别有趣的例子,因为ldtoken
IL指令不能将属性元数据标记作为参数,并且没有RuntimePropertyHandle类型。但是,可以在IL via中获得getter和/或setter方法(这不是有效的IL,但显示了说明)。不幸的是,在C#中没有直接的方法来生成具有typeof()
操作符提供的类型安全级别的代码
ldtoken <method>
call MethodBase.GetMethodFromHandle
ldtoken
调用MethodBase.GetMethodFromHandle
的答案显示了如何从MethodInfo获取PropertyInfo
Jon的答案对于您可能必须使用的解决方案来说是正确的。只需添加Jon Skeet所说的内容:即使在IL中也不可能。比方说,对于kicks,您可以通过编写自己的编译器,并将属性的元数据标记注入属性,来获取属性的MetadataToken。在运行时,您将无法要求属性来自的模块解析元数据令牌;您将收到以下消息: 此API不支持PropertyInfo令牌 测试这一点的一种方法是获取任何属性的
PropertyInfo
,并向定义包含属性的类型的模块询问resolvember
,该模块接受元数据标记的int
值,并向其提供PropertyInfo.MetadataToken
:
Console.WriteLine(propInfo.DeclaringType.Module.ResolveMember(propInfo.MetadataToken));
API并不是为这个目的而设计的,属性本身只是元数据,它随程序一起运行,帮助将方法关联到公共上下文,以便与编译器和IDE一起使用。一旦编译器接受了您的代码并发挥了它的魔力,该属性就不会在IL中出现一次
如果可以将属性的MetadataToken
推送到属性中,那么最好的办法是也将类型的MetadataToken
推送到属性中,并让它通过迭代类型的属性来检索PropertyInfo
对象,而具有匹配的MetadataToken
的将是您的目标
重要的是要理解,MetadataToken
s仅在其所在模块的范围内是唯一的。我会说组装,但多个模块组装扼杀了这个想法
我只从编写ECMA-335元数据解析器中了解到这一点。只是为了添加Jon Skeet所说的上下文:即使在IL中也不可能。比方说,对于kicks,您可以通过编写自己的编译器,并将属性的元数据标记注入属性,来获取属性的MetadataToken。在运行时,您将无法要求属性来自的模块解析元数据令牌;您将收到以下消息: 此API不支持PropertyInfo令牌 测试这一点的一种方法是获取任何属性的
PropertyInfo
,并向定义包含属性的类型的模块询问resolvember
,该模块接受元数据标记的int
值,并向其提供PropertyInfo.MetadataToken
:
Console.WriteLine(propInfo.DeclaringType.Module.ResolveMember(propInfo.MetadataToken));
API并不是为这个目的而设计的,属性本身只是元数据,它随程序一起运行,帮助将方法关联到公共上下文,以便与编译器和IDE一起使用。一旦编译器接受了您的代码并发挥了它的魔力,该属性就不会在IL中出现一次
如果可以将属性的MetadataToken
推送到属性中,那么最好的办法是也将类型的MetadataToken
推送到属性中,让它检索PropertyInfo
ob