【问题标题】:.NET Generics, pull object member value by name.NET 泛型,按名称提取对象成员值
【发布时间】:2014-08-01 18:27:56
【问题描述】:

我将 2 个通用对象和一个字符串传递给一个函数,我想找到与字符串匹配的对象的属性并比较它们的值。

这是一个示例模型:

Public Structure Foo
    Public Bar As String
    Public Nan As String
    Public Tucket As String
End Structure

和调用类:

<TestMethod()> 
Public Sub TestEquality_Class_Pass_Identifier()
    _tester = new GeneralAssert
    Dim expectedFoo = New Foo With {.Bar = "asdf", .Nan = "zxcv", .Tucket = "qwer"}
    Dim actualFoo = New Foo With {.Bar = "qwer", .Nan = "zxcv", .Tucket = "qwer"}
    _tester.TestEquality(expectedFoo, actualFoo, "Bar")
End Sub

执行业务逻辑的通用断言类

Public Class GenericAssert
    Public Sub TestEquality(Of t)(expected As t, actual As t, Optional identifier As String = Nothing)
        Dim expectedType = expected.GetType(), actualType = actual.GetType()
        Assert.AreEqual(expectedType, actualType)

        If (Not identifier Is Nothing) Then
            Dim expectedProperty = expectedType.GetMember(identifier).FirstOrDefault()
            Dim actualProperty = actualType.GetMember(identifier).FirstOrDefault()

            TestEquality(*WhatHere1*, *WhatHere2*)
        End If
    End Sub
End Class

预期结果将是比较 expectedFoo ("asdf") 和 actualFoo ("qwer") 的 Bar 成员。我在 FieldInfo、PropertyInfo 或 MemberInfo 中找不到任何可以让我按名称获取分配给该属性的值的值。

【问题讨论】:

  • .GetValue() 不会做吗?
  • expectedId.GetValue() 期望我传入一个对象,但 expectedId 是 Bar 对象,所以我没有要传入的内容。expected 没有 .GetValue()
  • expectedProperties.GetValue() sine 你已经建立了它被命名为identifier。你通过实例expectedFoo
  • expectedProperties 的类型为 MemberInfo()expectedProperties.GetValue(expectedId) 有一个编译器错误“参数类型不正确。候选是整数或长整数。
  • 看起来您正在尝试编写可重用的单元测试来比较对象;您可能想看看AutoFixtureIdiomsSemanticComparison 子项目,以及Albedo

标签: .net vb.net unit-testing reflection assert


【解决方案1】:

由于结构的性质和要测试的内容都是已知的,因此我使用 FieldInfo 对象作为获取字段值的最直接方式。

Public Sub TestEquality(Of t)(expected As t, actual As t, Optional identifier As String = Nothing)
    Dim expectedType = expected.GetType()
    Dim actualType = actual.GetType()

    Assert.AreEqual(expectedType, actualType)

    If (identifier IsNot Nothing) Then
        Dim expectedField As FieldInfo = expectedType.GetField(identifier, BindingFlags.IgnoreCase Or BindingFlags.Public Or BindingFlags.Instance)
        Dim actualField As FieldInfo = actualType.GetField(identifier, BindingFlags.IgnoreCase Or BindingFlags.Public Or BindingFlags.Instance)

        Assert.AreEqual(expectedField.GetValue(expected), actualField.GetValue(actual))
    End If
End Sub

【讨论】:

    【解决方案2】:

    我不明白为什么在这种情况下不会这样做:

    Public Sub AssertEquality(Of T)(ByVal expected As T, ByVal actual As T, identifier As String)
    
        Dim expected_prop = expected.GetType().GetProperty(identifier, BindingFlags.Instance + BindingFlags.Public)
        Dim actual_prop = actual.GetType().GetProperty(identifier, BindingFlags.Instance + BindingFlags.Public)
    
        Dim expected_value = expected_prop.GetValue(expected, Nothing)
        Dim actual_value = actual_prop.GetValue(actual, Nothing)
    
        Assert.AreEqual(expected_value, acutal_value)
    
    End Sub
    
    Sub Main()
    
        Dim expectedFoo = New Foo With {.Bar = "asdf", .Nan = "zxcv", .Tucket = "qwer"}
        Dim actualFoo = New Foo With {.Bar = "qwer", .Nan = "zxcv", .Tucket = "qwer"}
    
        AssertEquality(expectedFoo, actualFoo, "Bar")
    
    End Sub
    

    【讨论】:

    • GetValue() 的第一个参数根据我的编译器只能是 Integer 或 Long。其中expected 的类型为 t(或运行时为 Foo)
    • 另外,expected 是 Foo 类型,expected_prop 是 Foo 的属性列表,因此 expected_prop.GetValue(expected) 是 0 意义...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-19
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    相关资源
    最近更新 更多