代码之家  ›  专栏  ›  技术社区  ›  Don Edwards

结构上的反射与类不同,但仅在代码上不同

  •  5
  • Don Edwards  · 技术社区  · 17 年前

    代码段:

    Dim target As Object
    ' target gets properly set to something of the desired type
    Dim field As FieldInfo = target.GetType.GetField("fieldName", _
      BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic)
    field.SetValue(target,newValue)
    

    行得通 .

    关于发生了什么以及如何实际更改代码中的字段,有什么建议吗?

    根据Jon Skeet的请求,实际代码:

    Private Shared Function XmlDeserializeObject(ByVal objectType As Type, _
            ByVal deserializedID As String) As Object
        Dim result As Object
        result = CreateObject(objectType)
    
        mXmlR.ReadStartElement()
        Do While mXmlR.IsStartElement _
        AndAlso mXmlR.Name <> elementItem
            Dim field As FieldInfo = result.GetType.GetField(FullName, _
                BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic)
            field.SetValue(result, XmlDeserialize(field.FieldType))
        Loop
    
        Return result
    End Function
    


    *mXmlR是一个XmlTextReader,已正确初始化和定位(否则这在类上不起作用)
    *CreateObject工作(同上)
    *XmlDeserialize大部分都是有效的,而且目前正在讨论的是如何处理一个整数。唯一已知的问题是结构。

    至于如何检查值,我主要关注的是“局部变量”窗口,但我也在即时窗口中使用了print语句,我正在运行一个NUnit测试,但由于这个问题,该测试失败了,而使用类而不是结构的等效测试通过了。

    <Serializable()> Private Structure SimpleStructure
        Public MemberOne As Integer
    End Structure
    
    <Test()> Sub A016_SimpleStructure()
        Dim input As New SimpleStructure
        input.MemberOne = 3
        Dim st As String = Serialize(input)
        Debug.Print(st)
        Dim retObject As Object = Deserialize(st)
        Assert.IsNotNull(retObject)
        Assert.IsInstanceOfType(GetType(SimpleStructure), retObject)
        Assert.AreEqual(input.MemberOne, DirectCast(retObject, SimpleStructure).MemberOne)
    End Sub
    
    4 回复  |  直到 17 年前
        1
  •  7
  •   Ian Horwill    17 年前

    使用您的原始示例,我同意它可以在C#中工作,但不能在VB中工作!如果使用Reflector或ILDasm,您将看到对Field.SetValue(target,…)的调用实际上编译为(在VB中):

    field.SetValue(RuntimeHelpers.GetObjectValue(target), ...)
    

    GetObjectValue“如果obj是一个值类,则返回obj的装箱副本;否则返回obj本身。”即,在结构的副本上设置该值!

    This link

        2
  •  4
  •   Christian    13 年前

    国 领域 var至 西班牙 ( 是一个*St_WorldChampion*结构)。我们在这个过程中做出改变 x 冠军

    Public Structure St_WorldChampion
        Dim sport As String
        Dim country As String
    End Structure
    
    Sub UpdateWorldChampion()
        Dim champion As New St_WorldChampion, x As ValueType
        Dim prop As System.Reflection.FieldInfo
    
        ' Initial values: Germany was the winner in 2006
        champion.country = "Germany"
        champion.sport = "Football"
    
        ' Update the World Champion: Spain since 2010
        x = champion
        prop = x.GetType().GetField("country")
        prop.SetValue(x, "Spain")
        champion = CType(x, St_WorldChampion)
    
    End Sub
    
        3
  •  1
  •   Jon Skeet    17 年前

    嗯,您还没有显示所有代码,特别是您正在设置的位置 target 以及之后如何检查字段的值。

    下面是一个示例,它在C#中运行良好:

    using System;
    using System.Reflection;
    
    struct Foo
    {
        public int x;
    }
    
    class Test
    {
        static void Main()
        {
            FieldInfo field = typeof(Foo).GetField("x");
    
            object foo = new Foo();
            field.SetValue(foo, 10);
            Console.WriteLine(((Foo) foo).x);
        }
    }
    

    Foo foo = new Foo();
    object target = foo;
    // SetValue stuff
    
    // What do you expect foo.x to be here?
    

    价值 foo 当它被装箱时。您需要取消装箱,然后再次复制:

    foo = (Foo) target;
    

    如果不是这样,请展示一个简短但 完成

        4
  •  0
  •   Arthur JF    12 年前

    嗨,我用基督教的例子做了这个函数,希望对你有所帮助。

    ''' <summary>
    ''' Establece el -valor- en la -propiedad- en el -objeto-
    ''' Sets Value in Objeto.[propertyname]
    ''' </summary>
    ''' <param name="objeto">Object where we will set this property</param>
    ''' <param name="Propiedad">Name of the property</param>
    ''' <param name="valor">New Value of the property</param>
    ''' <returns>Object with changed property</returns>
    ''' <remarks>It works on structures!</remarks>
    Function Establecer_propiedad(objeto As Object, Propiedad As String, valor As Object) As Object
        'Check arguments
        If objeto Is Nothing Then Throw New ArgumentNullException("Objeto")
        If String.IsNullOrWhiteSpace(Propiedad) Then Throw New ArgumentNullException("Propiedad")
        'Get the object type
        Dim t As Type = objeto.GetType
        'Get the propertyInfo by its name
        Dim prop As PropertyInfo = t.GetProperty(Propiedad)
        'Check if the property exist
        If prop Is Nothing Then Throw New InvalidOperationException("Property does not exist")
        If Not prop.CanWrite Then Throw New InvalidOperationException("Property is read only")
        'Determine if it is a class or a structure
        If Not t.IsValueType Then ' (it is a reference value)
            'Set without troubles
            If prop.CanWrite Then prop.SetValue(objeto, valor)
            'Return object
            Return objeto
        Else '(It is a structure)
            'Create a box using a valuetype
            'It doesnot work in object
            Dim Box As ValueType
            'Set item in box
            Box = objeto
            'Set value in box
            prop.SetValue(Box, valor)
            'Return box
            Return Box
        End If
    End Function