-1

I have an XML file with classes name like this:

<ActiveMonitorsList>
        <MonitorName>CertificatesMonitor</MonitorName>
        <MonitorName>ServicesMonitor</MonitorName>
        <MonitorName>LogsMonitor</MonitorName>
        <MonitorName>DBMonitor</MonitorName>
</ActiveMonitorsList>

Each of this classes containts a method: bool SingleCheck();

I would like to execute this bool SingleCheck() method for each class that is in this XML file.

What is the best way to do this?

This is what I have so far - it doesn't work:

foreach (string monitorName in monitorsList)
{
    Type thisType = GetType();
    MethodInfo singleMonitorMethod = thisType.GetMethod("{monitorName}.SingleCheck");
    bool methodResult = singleMonitorMethod.Invoke(...);
}
  • In place of (...) - don't know what to put here, but I want to get the result of the method (it's always bool).
  • All of those methods I want to pass as paramters are static.
  • I guess delegates, Actions or Func<> have to go in here...

Thank You very much in advance!

Edit: Each name in XML points to a separate class. Each class have the same named method: public static bool SingleCheck(). What I want to do is:

  • get all the monitors names (classes names will be the same)
  • invoke a method (it has the same name in each class) inside EVERY class present on that list.

EDIT - PROBLEM SOLVED:

When I first created my project, I included separate folder for all monitors. Then I changed my mind, deleted this folder and added manually SAME FILES to my solution. In this way - those files still had "using <namespace>.Monitors"... And that's why I couldn't list those classes and the Types were still nulls...

Thanks for all suggestions ! ;)

Kamil Turowski
  • 427
  • 1
  • 4
  • 13
  • where do you execute the foreach loop? what `Type` do you expect from the call of `GetType()` ? – Mong Zhu Jul 16 '19 at 12:20
  • 1
    Possible duplicate of [Call static method with reflection](https://stackoverflow.com/questions/11908156/call-static-method-with-reflection) – Selvin Jul 16 '19 at 12:23
  • @Selvin It's not really a duplicate as here it's not just about invoking a MethodInfo for a static method, but also about to find the method within a type. – ckuri Jul 16 '19 at 12:28
  • I am looking for a CLASS name, the XML hold CLASSES names. Inside each of those public classes there is a method called SingleCheck(). This method is static. – Kamil Turowski Jul 16 '19 at 12:35
  • Edited the question, it's quite complex so I am not sure if this is understoodable. – Kamil Turowski Jul 16 '19 at 12:42

2 Answers2

2

I would suggest to take this overload of the method Invoke It wants an object(calling instance) and a set of input parameters for the method from you.

Since it is a static method, you can calmly pass null as the first parameter and because you method does not have any parameters you again can calmly pass null as the second value. Don't forget to cast object to the corresponding return type. In your case bool.

bool methodResult = (bool)singleMonitorMethod.Invoke(null, null);

To get the correct Type you actually need to know the namespace! So this would look like this:

foreach (string monitorName in monitorsList)
{
    string typeName = $"{yourNameSpace}.{monitorName}";
    Type thisType = Type.GetType(typeName);
    MethodInfo singleMonitorMethod = thisType.GetMethod("SingleCheck");
    bool methodResult = (bool)singleMonitorMethod.Invoke(null, null);
}

If the loop is in the same namespace this should also work:

Type thisType = Type.GetType($"{GetType().Namespace}.{monitorName}");
Mong Zhu
  • 23,309
  • 10
  • 44
  • 76
  • I have seperate public classes and in each of them there is the same method called "SingleCheck". I cannot use my namespace name directly. – Kamil Turowski Jul 16 '19 at 12:34
  • @KamilTurowski " I cannot use my namespace name directly" are the classes in different namespaces? – Mong Zhu Jul 16 '19 at 12:36
  • 1
    Well, they are all in the same namespace. Though - You suggested {yourNameSpace}.SingleCheck -> it doesn't return a class name - the one that I need. – Kamil Turowski Jul 16 '19 at 12:38
  • @KamilTurowski damn'it that is a big copy paste typo. Sorry for that I changed it I meant : `string typeName = $"{yourNameSpace}.CertificatesMonitor";` – Mong Zhu Jul 16 '19 at 12:41
  • Actually: string typeName = '$"{yourNameSpace}.{monitorName}' inside of the foreach loop. – Kamil Turowski Jul 16 '19 at 12:44
  • @KamilTurowski there is still my first question unanswered. Where is this loop situated? in a different class? same namespace as the names from XML? – Mong Zhu Jul 16 '19 at 12:51
  • 1
    Loop is inside of RoutineCheck() method, which is in timer in Main() method (it's console app), but it's still the same namespace ;) But yes, it's in different class then the every "monitor" method... – Kamil Turowski Jul 16 '19 at 12:57
  • @KamilTurowski happy to hear mate. If it is in the same namespace then you can get it by this call: `GetType().Namespace` – Mong Zhu Jul 16 '19 at 13:45
1

thisType.GetMethod("{monitorName}.SingleCheck") won't work because of two reasons. 1) You forgot the string interpolation $-sign and thus are searching for a method called "{monitorName}.SingleCheck" which obviously can't exist with such a name. 2) Instead of thisType you need to provide the type containing the method.

Invoke needs to be called with the instance as first parameter - null for static methods - and an object array for the method parameters.

Assuming that your monitor classes are in the same assembly like your current type you would need to do the following:

foreach (string monitorName in monitorsList)
{
  Type monitorType = GetType().Assembly.GetExportedTypes().Single(x => x.Name == monitorName);
  MethodInfo singleMonitorMethod = monitorType.GetMethod("SingleCheck");
  bool methodResult = (bool)singleMonitorMethod.Invoke(null, Array.Empty<object>());
}

I prefer Array.Empty over new object[0] or new object[] { } because it doesn't create a new object every time.

Edited: Changed the type discovery according to Mong Zhu's comment that GetType(monitorName) does need the fully-qualified name.

ckuri
  • 3,784
  • 2
  • 15
  • 17