我想獲得一個類的所有字段,而不需要獲取類事件的基礎實現。 type.GetFields(BindingFlags ...)爲事件字段返回親密的委託。有誰知道如何過濾出來?如何過濾作爲類事件基礎實現的FieldInfos?
回答
.NET中的事件生成一個與事件相同和類型的字段。另外,它們生成兩種方法(加法器和去除器,它們與具有前綴'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#
此代碼將工作在自動生成的事件(定製加法器或移除器將破壞代碼)。這也是一個有風險的代碼,它對加法器方法生成和編譯的方式做了一些假設。我將這些代碼發佈爲「學術」信息,我不會在生產代碼中使用它。
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;
}
這裏假設的是,加法器方法體中的字節3-6是事件的支持字段的標記。我真的希望有人會發佈一個優雅和安全的解決方案來解決這個問題:)
我希望能從反射API中得到更好的支持。我知道我可以這樣做,但接下來我必須以不同的方式實現VB(稱爲X的事件的底層字段是XEvent)。 – 2010-06-05 11:33:15
@Izik Shmulewitz,你說得對,我甚至不知道VB會產生不同的後臺字段。我添加了一些解決此問題的代碼,但它僅適用於使用默認加法器和刪除方法的事件。 – Elisha 2010-06-05 13:07:09
- 1. 以div節出現事件爲基礎
- 2. 爪哇 - 如何實現方法克隆爲基礎,派生類
- 3. 實現派生接口的基礎件
- 4. 基礎實體類。 NHibernate的
- 5. 使用SPDY作爲SOA相關實現的基礎傳輸
- 6. 如何在Python中實現shell作業控制基礎?
- 7. 如何在非基於VO的ADF RichTable中實現過濾器?
- 8. 如何實現基於不同標準的收集過濾
- 9. 如何使用不同的基礎實現實例化擴展類?
- 10. 過濾NSMutableArray的基礎上過濾另一個NSMutableArray
- 11. 如何在asp.net中實現用戶基礎安全而不是角色基礎?
- 12. 使用非抽象類作爲基礎
- 13. 過濾器是如何實現的?
- 14. 如何實現android的過濾器listview
- 15. 如何實現treetableview的過濾
- 16. 如何實現匹配的過濾器
- 17. Angularjs過濾器基礎知識
- 18. 碼頭資源基礎目錄過濾
- 19. 是否有可能將現有的類作爲.xsd文件的基礎jaxb
- 20. WPF - 爲基類實現System.ComponentModel.INotifyPropertyChanged
- 21. 如何建立基礎和模式實驗室,爲Drupal工作?
- 22. 設計模式的基礎上,實現
- 23. 如何基於關係實現Doctrine2過濾器?
- 24. 如何覆蓋CSS類的基礎類
- 25. 如何使用維度過濾事實?
- 26. 如何實現空間欄的actionListener作爲行動事件
- 27. 如何實現REST API的基礎servlet和Tomcat8與Spring/Hibernate的
- 28. 在Prolog中使用非基礎事實?
- 29. 如何在php中實現類似Angular的過濾器功能?
- 30. 如何在其他基礎上過濾Apache flink流?
你是什麼意思?如果您有一個名爲Container的對象並且它具有一個Container字段,那麼您不希望看到該字段? – Kiril 2010-05-26 00:40:37
當使用Action委託來反映帶有名爲NotifySomething的事件的類型時,類中將創建一個類型爲Action的私有字段,我不想獲取它。 – 2010-05-27 10:48:40