从程序集中获取类型时,有没有办法确定类型是否为匿名类型?

时间:2012-08-20 15:13:35

标签: vb.net unit-testing reflection anonymous-types

我在项目中添加了一个匿名类型:

'Put the courses from the XML file in an Anonymous Type
Dim courses = From myCourse In xDoc.Descendants("Course")
              Select New With
                  {
                      .StateCode = myCourse.Element("StateCode").Value, _
                      .Description = myCourse.Element("Description").Value, _
                      .ShortName = myCourse.Element("ShortName").Value, _
                      .LongName = myCourse.Element("LongName").Value, _
                      .Type = myCourse.Element("Type").Value, _
                      .CipCode = CType(myCourse.Element("CIPCode"), String) _
                }

For Each course In courses
    If Not UpdateSDECourseCode(acadYear, course.StateCode, course.Description, course.Type, course.ShortName, course.LongName, course.CipCode) Then errors.Add(String.Format("Cannot import State Course Number {0} with Year {1} ", course.StateCode, acadYear))
Next

执行此操作后,单元测试失败:

Public Function GetAreaTypeList() As List(Of Type)
    Dim types As New List(Of Type)
    Dim asmPath As String = IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "My.Stuff.dll")

    For Each t As Type In Reflection.Assembly.LoadFrom(asmPath).GetTypes()
        If t.Namespace.StartsWith("My.Stuff.BatchUpdater") Then
            If t.BaseType Is GetType(My.Stuff.BatchUpdater.Area) Then
                types.Add(t)
            End If
        End If
    Next

    Return types
End Function

失败是因为项目中添加了新类型( VB $ AnonymousType_0`6 ),并且没有名为命名空间的属性。

我通过对IF语句进行以下更改来修复:

If Not t.Namespace Is Nothing AndAlso t.Namespace.StartsWith("My.Stuff.BatchUpdater") Then

由于我不完全了解正在发生的事情,我对我的代码更改感到遗憾。

为什么匿名类型的命名空间没什么?

您会以同样的方式修复单元测试吗?或者它应该是更具体的东西(例如如果不是t.Names =“VB $ AnonymousType_0`6”


更新

decyclone给了我创建更好测试所需的信息:

For Each t As Type In Reflection.Assembly.LoadFrom(asmPath).GetTypes()
    'Ignore CompilerGeneratedAttributes (e.g. Anonymous Types)
    Dim isCompilerGeneratedAttribute = t.GetCustomAttributes(False).Contains(New System.Runtime.CompilerServices.CompilerGeneratedAttribute())

    If Not isCompilerGeneratedAttribute AndAlso t.Namespace.StartsWith("My.Stuff.BatchUpdater") Then
         '...Do some things here
    End If
Next

老实说,使用LINQ查询可以进一步改进,但这适合我。

1 个答案:

答案 0 :(得分:1)

匿名方法和类型使用 CompilerGeneratedAttribute 进行修饰。您可以检查他们是否存在以识别匿名类型。

var anonymous = new { value = 1 };

Type anonymousType = anonymous.GetType();
var attributes = anonymousType.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false);

if (attributes.Any())
{
    // Anonymous
}

您可以在测试中过滤掉这些内容。

还可以使用 CompilerGeneratedAttribute 标记用户定义的类型。所以也许你可以将它与检查命名空间是否为空

结合起来
var anonymous = new { value = 1 };

Type anonymousType = anonymous.GetType();
var attributes = anonymousType.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false);

if (attributes.Any() && anonymousType.Namespace == null)
{
    // Anonymous
}