Получить адрес памяти ссылки на строку byref - PullRequest
1 голос
/ 15 марта 2011

Я экспериментирую с более эффективными способами создания форм.Мои эксперименты связаны с возможностью связывать строки и другие типы напрямую по ссылкам на их классы и использовать их для обновления исходных значений без какого-либо строго типизированного кода.

Я использовал GCHandle.AddrOfPinnedObject, чтобы получить адрес памяти строки, но он дает адрес памяти строковых данных, а не класс / ссылку на строку, которые мне нужно изменить, чтобы позволить мне использоватьэтот подход.

Я знаю, что строки являются неизменяемыми и не могут быть изменены (На самом деле, вы можете, но это не рекомендуется), но я не хочу изменять фактические строки, но изменить ссылку на него(строковый объект).

Есть ли другой способ получить адрес ссылки на строковый объект?

Пример кода:

Private oTestperson As New Person

Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    ' Create the form
    AddText("Name", oTestperson.Name)
    AddText("Phone", oTestperson.Phone)
    AddText("Address", oTestperson.Address)

End Sub

Public Sub AddText(ByVal Title As String, ByRef sValue As String)

    Dim oGCHandle As System.Runtime.InteropServices.GCHandle
    Dim oInputItem As New InputItem

    ' This does not do the job, as it only returns the address of the string data, not the reference to the string class
    oGCHandle = System.Runtime.InteropServices.GCHandle.Alloc(CType(sValue, Object), System.Runtime.InteropServices.GCHandleType.Pinned)
    oInputItem.Pointer = oGCHandle.AddrOfPinnedObject()
    oGCHandle.Free()

    ' Store data
    oInputItem.ID = GetID()
    oInputItem.Type = InputTypes.Text
    oInputItem.BaseValue = sValue
    If Not Request.Form(oInputItem.ID) Then oInputItem.Value = Request.Form(oInputItem.ID)
    If oInputItem.Value Is Nothing Then oInputItem.Value = sValue

    ' Save in collection
    InputItems.Add(oInputItem)

End Sub

Private Sub linkbuttonSave_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles linkbuttonSave.Click
    Save()
End Sub

Public Sub Save()

    Dim oTest As New Person
    Dim oGCHandle As System.Runtime.InteropServices.GCHandle
    Dim NewStrPointer As IntPtr

    ' Check if something has been changed, in that case update the origional value
    For Each oInputItem As InputItem In InputItems
        If oInputItem.Value <> oInputItem.BaseValue Then
            oGCHandle = GCHandle.Alloc(oInputItem.Value, GCHandleType.Pinned)
            NewStrPointer = oGCHandle.AddrOfPinnedObject()
            oGCHandle.Free()

            ' This fails as oInputItem.Pointer is the address of the string data, not the string class
            Marshal.WriteInt32(oInputItem.Pointer.ToInt32, NewStrPointer.ToInt32)

        End If
    Next

End Sub

Private InputItems As New ArrayList

Private Class Person
    Public Property Name As String
    Public Property Phone As String
    Public Property Address As String
End Class

Public Enum InputTypes As Integer
    Text = 0
End Enum

Public Class InputItem

    Public Property ID As String
    Public Property BaseValue As Object
    Public Property Value As Object
    Public Property Type As InputTypes = 0
    Public Property Pointer As IntPtr

End Class

Ответы [ 2 ]

0 голосов
/ 15 марта 2011

Ваш подход немного C ++ / VB6 / конца 90-х, но 10 для усилий!:)

Чтение System.Reflection для итерации классов , DataBinding для привязки (данных) классов к графическому интерфейсу и сериализации для чтения / письма.Использование WPF еще больше упростит задачу почти до нуля (Примечание. WPF можно использовать в WinForms через ElementHost .

0 голосов
/ 15 марта 2011

Одобренный способ сделать это - использовать отражение, это будет намного проще, и CLR сможет гарантировать, что вы не разбрасываете объекты повсюду.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...