簡體   English   中英

列出方法並在運行時調用它們

[英]List methods and invoke them at runtime

情況如下:

我想創建一個測試應用程序,該應用程序將能夠檢索dll中的所有類和方法,並允許我在運行時調用它們。

我所擁有的是這樣的:

假設我有那些課程:

public static class FirstManagerSingleton
{
    public static SecondManager Instance
    {
       return mInstance; // which is a SecondManager private static object
    }
}

public class SecondManager
{
    public Service1 service1 {get; private set;}
    public Service2 service2 {get; private set;}
    ...
}

public class Service1
{
    public bool Method1()
    {
      return true;
    }
    public int Method2()
    {
      return 1;
    }
    ...
}

public class Service2
{
    public bool Method1()
    {
      return false;
    }
    public int Method2(int aNumber)
    {
      return aNumber - 1;
    }
    ...
}

我希望能夠選擇每個“服務”類,調用任何方法並顯示其結果。

是否可以使用反射來做到這一點? 如果不是多層結構(第2個經理類),那么我就不會那么掙扎。 事實是我需要通過如下所示的調用來訪問服務類:

FirstManagerSingleton.Instance.Service1.Method1;

到目前為止,我已經能夠加載程序集並檢索幾乎所有方法並進行打印。

Assembly assembly = Assembly.LoadFrom("assemblyName");

// through each type in the assembly
foreach (Type type in assembly.GetTypes())
{
  // Pick up a class
  if (type.IsClass == true)
  {
    MethodInfo[] methodInfo;
    Console.WriteLine("Found Class : {0}", type.FullName);
    Type inter = type.GetInterface("I" + type.Name, true);
    if (inter != null)
    {
      methodInfo = inter.GetMethods();
      foreach (MethodInfo aMethod in test2)
      {
        Console.WriteLine("\t\tMethods : " + aMethod);
      }
    }
  }
}

從那里,我真的不知道下一步該怎么調用這些方法。 順便說一下,這些方法可以采用一些參數並具有某些返回類型。

我正在使用該接口檢索方法,以便從另一個接口繼承的方法中進行過濾。

我希望我足夠清楚。 抱歉,我無法發布真實的代碼示例,但我想足以說明這個概念。

您應該從程序集中獲取類,然后以遞歸方式獲取屬性值並執行方法。 這是一些應根據需要定制的簡單代碼:

    public void ExecuteAssembly(string anAssemblyName)
    {
        Assembly assembly = Assembly.LoadFrom(anAssemblyName);

        foreach (Type type in assembly.GetTypes())
        {
            if (type.IsClass)
            {
                TypeAttributes atts = type.Attributes;
                if ((atts & TypeAttributes.Sealed) != 0) // identify the static classes
                    ExecuteEverything(type);
            }
        }
    }

    private void ExecuteEverything(Type type)
    {
        // get only the public STATIC properties and methods declared in the type (i.e. not inherited)
        PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
        MethodInfo[] meths = type.GetMethods(BindingFlags.Public | BindingFlags.Static 
            | BindingFlags.DeclaredOnly);
        // execute the methods which aren't property accessors (identified by IsSpecialMethod = true)
        foreach (MethodInfo aMeth in meths)
            if (!aMeth.IsSpecialName)
                Execute(aMeth, type);
        // for each property get the value and recursively execute everything
        foreach (PropertyInfo aProp in props)
        {
            object aValue = aProp.GetValue(type, null);
            if (aValue != null)
                RecursivelyExecuteEverything(aValue);
        }
    }

    private void RecursivelyExecuteEverything(object aValue)
    {
        Type type = aValue.GetType();
        // get only the public INSTANCE properties and methods declared in the type (i.e. not inherited)
        PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
        MethodInfo[] meths = type.GetMethods(BindingFlags.Public | BindingFlags.Instance
            | BindingFlags.DeclaredOnly);
        // execute the methods which aren't property accessors (identified by IsSpecialMethod = true)
        foreach (MethodInfo aMeth in meths)
            if (!aMeth.IsSpecialName)
                Execute(aMeth, aValue);
        // for each property get the value and recursively execute everything
        foreach (PropertyInfo aProp in props)
        {
            object newValue = aProp.GetValue(aValue, null);
            if (newValue != null)
                RecursivelyExecuteEverything(newValue);
        }

    }

    private void Execute(MethodInfo aMeth, object anObj)
    {
        // be careful that here you should take care of the parameters. 
        // this version doesn't work for Method2 in Service2, since it 
        // requires an int as parameter
        aMeth.Invoke(anObj, null);
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM