I have a case which is very similar to the case below:
Get all inherited classes of an abstract class
I have two classes which inherited to a base class
this is my base class:
public abstract class InputModule
{
public string ModuleName;
public int NumberOfInputFields;
}
And this is the first inhertied class:
public class Module1 : InputModule
{
new public string ModuleName = "FilmMusic";
public new int NumberOfInputFields = 7;
}
second:
public class Module2 : InputModule
{
new public string ModuleName = "MovieStaffInfo";
public new int NumberOfInputFields = 4;
}
And I want to get the value of ModuleName: "FilmMusic" and "MovieStaffInfo".
With the value, before user entering the main form, I could add a new UI (UI for FilmMusic Module and another UI for MovieStaff) to the main form.
And below were the codes I have used (most referred to the case I have mentioned above):
public void detectTotalNumberOfSector()
{
IEnumerable<InputModule> exporters = typeof(InputModule).Assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(InputModule)) && !t.IsAbstract).Select(t => (InputModule)Activator.CreateInstance(t));
foreach (var item in exporters)
{
Console.WriteLine(item.ModuleName);
}
}
And I got the output "null, null"
And I added those codes inside the foreach loop:
FieldInfo info = item.GetType().GetField("ModuleName");
Console.WriteLine(info.GetValue(item));
I have got what I want "FilmMusic, MovieStaffInfo".
I am a little bit confuse, what the elements inside the exporters collection ?
At first, I guess the item
is an instantiation of class Module1
, Module2
...,therefore I could use item.ModuleName
to access the value of ModuleName
.
Actually, I can't, I have to use FieldInfo
and GetValue
to access the field value, but it is also strange, because using GetValue
I have to create an instantiation first as a parameter assign to GetValue
(in my case, the item
is an instantiation of class Module1
,Module2
... I guess).
So, are the items of the collection exporters an instantiation of class Module1, Module2 or not?
If they are, why I got null when using item.ModuleName
?
Thanks for any opinion~
You've defined ModuleName
with the new
keyword (e.g. new public string ModuleName
). This means that if the variable pointing at the instance is typed as the base class, it won't be able to see the "new" field.
If you want to be able to see the module names, you have two options.
Get rid of the new
keyword. Instead, declare the member as an override, e.g.
public override string ModuleName = "etc.";
Use reflection to invoke the field on the derived type, e.g.
Console.WriteLine
(
item.GetType()
.GetField("ModuleName", BindingFlags.Instance | BindingFlags.Public)
.GetValue(item)
);
See also Difference between new and overrride
Personally I recommend the first option. It is unusual to need the new
keyword.