The main question I have is: Is it possible in reflection to distinguish a field of some delegate type from a field which is used by an event as storagefield? That comes down to the question: does the FieldInfo class contain information about whether it belongs to an event, as storagefield ? I can't find any properties which might tell, nor custum attributes.
In the code below, the relevant properties of both FieldInfos of SomeField and SomeEvent are identical. So I don't know how to sort FieldInfos based on whether they are eventstoragefields or not.
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace Test
{
class Program
{
public Action SomeField;
public event Action SomeEvent;
static void Main(string[] args)
{
FieldInfo[] fields = typeof(Program).GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo fi in fields)
Console.WriteLine(string.Format("FieldName: {0}, Accessibility: {1}, Has Attributes: {2}.", fi.Name, fi.Attributes,
fi.GetCustomAttributes(true).Length != 0));
Console.ReadLine();
}
}
}
One solution is to search for an eventInfo with exactly the same name, but I don't know whether that is foolproof and frankly, I would not be satisfied with that solution. There must be a more direct way.
You have defined field-like event:
C# language spec:
When compiling a field-like event, the compiler automatically creates storage to hold the delegate, and creates accessors for the event that add or remove event handlers to the delegate field.
How compiler generates name for storage field is unspecified. Usually this name of field matches with the name of event, so you will have two members with the same name (SomeName in your example), but different member types and different visibility (event - public, field - private).
Type.GetMember():
The GetMembers method does not return members in a particular order, such as alphabetical or declaration order. Your code must not depend on the order in which members are returned, because that order varies.
If you take overload of GetMembers() without parameters then it should return only public members - event. However if you use another overload (that accepts BindingFlags) with BindingFlags.NonPublic - then it will return both field and event in unspecified order, so you can't rely that first element you get will be event.
Use the MemberInfo.MemberType property. It will return Field/Event. RtFieldInfo is the type of the FieldInfo object representing the field (fieldInfo.GetType()), not the type of field (fieldInfo.MemberType).
class Program {
public event Action<Program> SomeEvent;
public Action<Program> SomeField;
static void Main(string[] args) {
var members = typeof (Program).GetMembers();
var eventField = members.First(mi => mi.Name == "SomeEvent");
var normalField = members.First(mi => mi.Name == "SomeField");
Console.WriteLine("eventField.MemberType: {0}", eventField.MemberType);
Console.WriteLine("normalField.MemberType: {0}", normalField.MemberType);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With