[英]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.