2011-03-15 58 views
1

我正在嘗試更有效的方式來生成表單。我的實驗可以直接通過它們的類引用來鏈接字符串和其他類型,並使用它來更新原始值而不使用任何強類型代碼。獲取byref參考字符串的內存地址

我一直在使用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 
+0

所以實質上你想要的是指針的地址而不是指針指向的地址?這樣你就可以直接指向指針通過改變指針的地址引用其他字符串?我在這裏丟失了什麼嗎? – 2011-03-15 16:10:03

+2

這裏有不止一個錯誤,你調用GCHandle.Free()之後,你獲得的指針不再指向一個固定的對象。想寫這樣的代碼,然後使用C或C++。C++/CLI是一種很好的語言,可以讓你同時執行這兩種操作。 – 2011-03-15 17:32:07

+0

正確,我需要指針的地址,而不是指針指向的地址。 GCHandler.Free()我在測試時沒有釋放處理程序,看起來像製作一個C++「不安全」的dll可能是成爲那麼可以做到這一點。 – 2011-03-16 07:19:41

回答

0

批准的方式做到這一點是使用反射,這將是更容易和CLR就能確保不會詆譭對象所有的地方。

0

你的方法是有點C++/VB6/90年代末,但10的努力! :)

閱讀System.Reflectioniterating classes,DataBinding爲綁定(數據)類GUI和Serialization讀/寫類。使用WPF將進一步簡化任務到接近虛無(注意WPF可以在WinForms中通過ElementHost使用

+0

是的,但該解決方案不會像我想要完成的那樣優雅。 – 2011-03-16 07:22:46