【问题标题】:How do I filter out <>c_DisplayClass types when going through types via reflection?通过反射处理类型时如何过滤掉 <>c_DisplayClass 类型?
【发布时间】:2012-08-07 13:23:34
【问题描述】:

我正在尝试创建一个单元测试,以确保我的所有业务类(我称之为命令和查询类)都可以使用 Windsor 解决。我有以下单元测试:

    [TestMethod]
    public void Windsor_Can_Resolve_All_Command_And_Query_Classes()
    {
        // Setup
        Assembly asm = Assembly.GetAssembly(typeof(IUnitOfWork));
        IList<Type> classTypes = asm.GetTypes()
                                    .Where(x => x.Namespace.StartsWith("MyApp.DomainModel.Commands") || x.Namespace.StartsWith("MyApp.DomainModel.Queries"))
                                    .Where(x => x.IsClass)
                                    .ToList();

        IWindsorContainer container = new WindsorContainer();
        container.Kernel.ComponentModelBuilder.AddContributor(new SingletonLifestyleEqualizer());
        container.Install(FromAssembly.Containing<HomeController>());

        // Act
        foreach (Type t in classTypes)
        {
            container.Resolve(t);
        }
    }

这会失败,但出现以下异常:

No component for supporting the service MyApp.DomainModel.Queries.Organizations.OrganizationByRegistrationTokenQuery+<>c__DisplayClass0 was found

我知道 &lt;&gt;c__DisplayClass0 类型是由于 Linq 正在编译,但是如何在不硬编码 Linq 查询中的名称的情况下过滤掉这些类型?

【问题讨论】:

    标签: c# reflection


    【解决方案1】:

    我会检查每个类型的 System.Runtime.CompilerServices.CompilerGeneratedAttribute 放在这些上。

    您可以使用Type.IsDefined,因此代码如下所示:

    foreach (Type type in classTypes)
    {
       if (type.IsDefined (typeof (CompilerGeneratedAttribute), false))
          continue;
    
       // use type...
    }
    

    【讨论】:

    • 您可以使用type.IsDefined 让生活变得更简单。
    • @Jon,谢谢!我必须记住 IsDefined... 更简洁!
    • 自 VS2015 以来运行良好的使用反射的代码可能会被破坏!我有从 MethodCall 返回正确表达式(List&lt;T&gt;)的代码。现在它返回一个&lt;&gt;c__DisplayClass36_0).CS$&lt;&gt;8__locals1。请注意,这是一个MemberExpression(它是一个包含列表作为值的ConstantExpression)。现在我必须遵循这个额外的间接方法,然后获取 CS$&lt;&gt;8__locals1 字段的值才能获取我的列表。
    • 就像@Cameron MacFarland 提到的,这不适用于嵌套类。
    【解决方案2】:

    显然嵌套类没有将[CompilerGenerated] 属性应用于它们。

    我想出了这个简单的方法来处理这种情况。

    bool IsCompilerGenerated(Type t) {
        if (t == null)
            return false;
    
        return t.IsDefined(typeof(CompilerGeneratedAttribute), false)
            || IsCompilerGenerated(t.DeclaringType);
    }
    

    表现出这种行为的类如下所示:

    class SomeClass {
        void CreatesADisplayClass() {
            var message = "foo";
    
            Action outputFunc = () => Trace.Write(message);
    
            Action wheelsWithinWheels = () =>
            {
                var other = "bar";
    
                Action wheel = () => Trace.WriteLine(message + " " + other);
            };
        }
    }
    

    【讨论】:

    • 我在接受 Mono 时遇到了问题,因为 Mono 生成的东西有点不同(显然)。这完美地工作。谢谢。
    【解决方案3】:

    检查[CompilerGenerated] 属性是否存在。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-02
      • 1970-01-01
      • 2013-02-02
      • 2010-10-07
      • 1970-01-01
      相关资源
      最近更新 更多