代码之家  ›  专栏  ›  技术社区  ›  Loren Pechtel

在C中查找包含方法的所有类#

  •  5
  • Loren Pechtel  · 技术社区  · 14 年前

    我想在名称空间中的所有类中搜索包含某个方法的类。如果一个类包含一个方法,那么我想创建该类的一个实例并运行该方法。

    显然,我必须从反思开始,但我坚持要去哪里。

    编辑:

    接口不是我想这样做的方式。

    我要找的是将测试函数嵌入到代码中,但只需要一个调用接口。如果有自测函数,请调用它。如果没有,忽略它。

    3 回复  |  直到 14 年前
        1
  •  11
  •   Community George Stocker    7 年前

    创建一个声明方法的接口,然后让各种类实现该接口。

    然后可以使用反射 find all types within an assembly that implement that interface .

    在那里,您需要创建每种类型的实例,然后调用该方法。具体的实现细节将根据您的尝试而有所不同。

    根据评论更新:

    我仍然认为接口(或属性)是可行的。这就是它如何与接口一起工作。

    interface ISelfTester
    {
        void SelfTest();
    }
    
    class SomeClass : ISelfTester
    {
        /* ... */
    
        public void SelfTest() 
        {
            // test code
        }
    
        /* ... */
    }
    

    然后您可以调用每种类型的自测试方法,如so(借用达坦和达伦Kopp):

    var type = typeof(ISelfTester);
    var types = AppDomain.CurrentDomain.GetAssemblies()
        .Select(x => x.GetTypes())
        .SelectMany(x => x)
        .Where(x => x.Namespace == "My.Name.Space" && type.IsAssignableFrom(x));
    
    foreach (Type t in types)
    {
        ISelfTester obj = Activator.CreateInstance(t) as ISelfTester;
        obj.SelfTest();
    }
    
        2
  •  11
  •   Dathan    14 年前

    如果没有关于该方法的区别的更多信息,我只假设它是按名称区分的,并且是公开的。名称假设是危险的,所以我不建议这样做,但是下面应该做你想做的(假设 Activator 能够创建实例)。

    编辑 :增加 Where(x => x.Namespace == "My.Name.Space") 将结果限制为单个目标命名空间。

    编辑 :增加 if ... else 处理静态方法的情况。

    var methods = AppDomain.CurrentDomain.GetAssemblies()
        .Select(x => x.GetTypes())
        .SelectMany(x => x)
        .Where(x => x.Namespace == "My.Name.Space")
        .Where(c => c.GetMethod("MethodName") != null)
        .Select(c => c.GetMethod("MethodName"));
    
    foreach (MethodInfo mi in methods)
    {
        if (mi.IsStatic)
        {
            mi.Invoke(null, null); // replace null with the appropriate arguments
        }
        else if (!mi.DeclaringType.IsAbstract)
        {
            var obj = Activator.CreateInstance(mi.DeclaringType);
            mi.Invoke(obj, null); // replace null with the appropriate arguments
        }
    }
    

    但是,如果您可以控制这些类型,JRummel关于接口的建议是一种更安全的方法。

        3
  •  2
  •   Dan Bryant    14 年前

    一种选择是使用反射,如上所述,但不是按名称查找方法,而是查找用适当的自定义属性标记的方法。这类似于MS DataContractSerializer使用以下属性所做的操作 [OnDeserializing] . 通过这种方式,类实现者明确地说明了他们对方法的意图,而不是让它突然做一些由于它有一个特定的名称而引起的意外的事情。

    另一方面,由于您所追求的是一种测试方法,因此您可能会发现 NUnit . 有几个优秀的免费单元测试框架。它们还提供了可以帮助您进行测试的其他特性,因为它们为您可能想要进行的不同类型的测试断言提供了框架。