【问题标题】:How to figure out dynamically all methods with custom attribute如何动态计算所有具有自定义属性的方法
【发布时间】:2013-09-19 21:29:13
【问题描述】:

我有一个简单的挑战。我需要动态地找出 C# 中具有特定属性的所有方法。我将从另一个应用程序动态加载程序集,并且需要找出确切的方法。程序集如下所示:

Base.dll:

 Class Base
   {
   [testmethod]
   public void method1()
   ... 
   }

Derived.dll:

 Class Derived:Base
  {
   [testmethod]
   public void method2()
  }

现在在第三个应用程序中,我喜欢动态加载上述 dll 并找出测试方法。

如果我加载 Base.dll,我需要获取 testmethod1。如果我加载Drived.dll,我应该得到testmethod1和testmethod2吗?

我在网上找到了一些帮助我动态加载 dll 的代码:

 List<Assembly> a = new List<Assembly>();

    string bin = @"Bin-Folder";

    DirectoryInfo oDirectoryInfo = new DirectoryInfo(bin);

    //Check the directory exists
    if (oDirectoryInfo.Exists)
    {
     //Foreach Assembly with dll as the extension
     foreach (FileInfo oFileInfo in oDirectoryInfo.GetFiles("*.dll", SearchOption.AllDirectories))
     {

      Assembly tempAssembly = null;

     //Before loading the assembly, check all current loaded assemblies in case talready loaded
    //has already been loaded as a reference to another assembly
    //Loading the assembly twice can cause major issues
    foreach (Assembly loadedAssembly in AppDomain.CurrentDomain.GetAssemblies())
    {
     //Check the assembly is not dynamically generated as we are not interested in these
     if (loadedAssembly.ManifestModule.GetType().Namespace != "System.Reflection.Emit")
     {
       //Get the loaded assembly filename
        string sLoadedFilename =
                                loadedAssembly.CodeBase.Substring(loadedAssembly.CodeBase.LastIndexOf('/') + 1);

      //If the filenames match, set the assembly to the one that is already loaded
        if (sLoadedFilename.ToUpper() == oFileInfo.Name.ToUpper())
        {
            tempAssembly = loadedAssembly;
            break;
        }
      }
     }

     //If the assembly is not aleady loaded, load it manually
     if (tempAssembly == null)
     {
         tempAssembly = Assembly.LoadFrom(oFileInfo.FullName);
     }
     a.Add(tempAssembly); 
    } 

上面的代码工作正常,我可以加载 DLL。但是,当我使用以下代码找出正确的方法时,它不会返回任何所需的结果。我想知道哪个部分不正确。以下代码列出了大约 145 种方法,但其中没有一个是我正在寻找的。​​p>

public static List<string> GetTests(Type testClass)
{
 MethodInfo[] methodInfos = testClass.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance);
 Array.Sort(methodInfos,
       delegate(MethodInfo methodInfo1, MethodInfo methodInfo2)
 { return methodInfo1.Name.CompareTo(methodInfo2.Name); });

 foreach (MethodInfo mi in methodInfos)
 {
   foreach (var item in mi.GetCustomAttributes(false))
     {
      if
     (item.ToString().CompareTo("Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute") == 0)
                    result.Add(mi.Name);
            }
        }

        return result;
   }

谁能帮我解决这个问题?

我不知道为什么,但我尝试从上述类(基类和派生类)实例化对象,并且上述代码返回了正确的结果。但是如上所述,如果我没有来自基类和派生类的对象并尝试根据类型找出方法,它不会返回所需的结果。

谢谢

【问题讨论】:

    标签: c# reflection dll methods assemblies


    【解决方案1】:

    最简单的方法是使用MethodInfo.IsDefined - 很可能也与 LINQ 一起使用:

    var testMethods = from assembly in assemblies
                      from type in assembly.GetTypes()
                      from method in type.GetMethods()
                      where method.IsDefined(typeof(TestMethodAttribute))
                      select method;
    
    foreach (var method in testMethods)
    {
        Console.WriteLine(method);
    }
    

    (我也会使用 LINQ 进行所有排序。例如,您可以调整 GetMethods 调用等以仅返回实例方法。)

    我并不完全清楚为什么您当前的方法不起作用,或者为什么在您创建实例时它确实起作用 - 但如果没有一个简短但完整的示例来说明问题,那就是很难进一步诊断。我肯定会从上面的代码开始 :)

    【讨论】:

    • 谢谢。您的建议帮助我走得更远,但并没有完全解决我的问题。如果我删除过滤器部分,我会得到整个方法列表,包括我正在寻找的方法,但是一旦我使用“Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute”添加过滤器,我就没有收到任何结果。我仔细检查了加载的文件和真正用 [TestMethod] 属性标记的方法。我迷失了为什么它仍然无法正常工作并且没有使用“testmethod”属性整理所有方法。
    • 谢谢。我终于找到了解决方案。那是我的错误。我添加了一个旧版本的 unitTestFrameWork,它导致了所有这些奇怪的问题。一旦我提到正确的版本,它就会命中所有方法。再次感谢。
    猜你喜欢
    • 2020-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-08
    • 2013-04-10
    • 2018-07-30
    • 1970-01-01
    相关资源
    最近更新 更多