gpt4 book ai didi

c# - 如何过滤作为类事件底层实现的 FieldInfo?

转载 作者:太空宇宙 更新时间:2023-11-03 14:29:55 26 4
gpt4 key购买 nike

我想获取类的所有字段,但不获取类事件的底层实现。type.GetFields(BindingFlags...) 返回事件字段的核心委托(delegate)。有谁知道如何过滤掉它们?

最佳答案

.NET 中的事件生成一个与事件具有相同类型的字段。此外,它们还生成两个方法(adder 和 remover,它们与带有前缀“add_”和“remove_”的字段同名)。

为了过滤事件支持字段,您可以删除与事件同名的字段。您可以确定不会定义与事件同名的字段,因为如果用相同的名称定义另一个成员,编译器将编译失败。

例如:

public IEnumerable<FieldInfo> FilterBackingEventFields(Type type)
{
List<string> eventNames = type
.GetEvents().Select(eventInfo => eventInfo.Name).ToList();

FieldInfo[] fieldInfos = type
.GetFields(BindingFlags.NonPublic |
BindingFlags.Public |
BindingFlags.Instance);

return fieldInfos.Where(fieldInfo => !eventNames.Contains(fieldInfo.Name));
}

使用示例:

public class ClassWithEventAndField
{
public event EventHandler MyEvent;
public int MyField;
}

[Test]
public void TestFieldsFilter()
{
IEnumerable<FieldInfo> fields =
FilterBackingEventFields(typeof(ClassWithEventAndField));

FieldInfo expectedField = typeof(ClassWithEventAndField).GetField("MyField");
Assert.That(fields, Is.EquivalentTo(new[] { expectedField }));
}

编辑:添加了对使用 VB 和 C# 的支持

此代码适用于自动生成的事件(自定义添加器或删除器将破坏代码)。这也是一个有风险的代码,它对 adder 方法的生成和编译方式做了一些假设。我将此代码作为“学术”信息发布,我不会在生产代码中使用它。

public IEnumerable<FieldInfo> FilterBackingEventFields(Type type)
{
List<int> backingFieldsTokens = type
.GetEvents().Select(eventInfo => MetadataToken(eventInfo)).ToList();

FieldInfo[] fieldInfos = type
.GetFields(BindingFlags.NonPublic |
BindingFlags.Public |
BindingFlags.Instance);

return fieldInfos
.Where(fieldInfo => !backingFieldsTokens.Contains(fieldInfo.MetadataToken));
}

private static int MetadataToken(EventInfo eventInfo)
{
MethodInfo adderMethod = eventInfo.GetAddMethod();
int fieldToken =
adderMethod.GetMethodBody().GetILAsByteArray()[3] |
adderMethod.GetMethodBody().GetILAsByteArray()[4] << 8 |
adderMethod.GetMethodBody().GetILAsByteArray()[5] << 16 |
adderMethod.GetMethodBody().GetILAsByteArray()[6] << 24;

return fieldToken;
}

这里做的假设是adder方法体中的字节3-6是事件的backing field的token。我真的希望有人能发布一个优雅而安全的解决方案来解决这个问题:)

关于c# - 如何过滤作为类事件底层实现的 FieldInfo?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2905960/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com