0

これが状況です:

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);
      }
    }
  }
}

そこから、メソッドを呼び出すために次に何をすべきか本当にわかりません。ちなみに、これらのメソッドはいくつかのパラメーターを取り、いくつかの戻り型を持つことができます。

別のインターフェイスから継承されたメソッドからフィルタリングするために、インターフェイスを使用してメソッドを取得しています。

私は十分に明確だったと思います。申し訳ありませんが、実際のコードサンプルを投稿することはできませんが、概念を説明するには十分だと思います。

4

1 に答える 1

1

アセンブリからクラスを取得してから、プロパティ値を再帰的に取得してメソッドを実行する必要があります。必要に応じて調整する必要のある簡単なコードを次に示します。

    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);
    }
于 2012-09-13T10:26:15.210 に答える