2011-03-15 61 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