tags:

views:

54

answers:

3

Rather than giving the very specific case (which I did earlier), let me give a general example. Let's say that I have a function, called callingFunction. It has one parameter, called parameter. Parameter is of an unknown type. Let us then say that I wish to copy this parameter, and return it as a new object. For example, in pseudo code, something along the lines of...

Function callingFunction(ByVal parameter As Object) As Object

    Dim newObj As New Object

    'newObj has the same value as parameter, but is a distinctly different object
    'with a different reference

    newObj = parameter

    return newObj

End Function

EDIT: Additional Information

The first time I posted this question, I received only one response - I felt that perhaps I made the question too specific. I guess I will explain more, perhaps that will help. I have an ASP page with 10 tables on it. I am trying, using the VB code behind, to come up with a single solution to add new rows to any table. When the user clicks a button, a generic "add row" function should be called.

The difficulty lies in the fact that I have no guarantee of the contents of any table. A new row will have the same contents as the row above it, but given that there are 10 tables, 1 row could contain any number of objects - text boxes, check boxes, etc. So I want to create a generic object, make it of the same type as the row above it, then add it to a new cell, then to a new row, then to the table.

I've tested it thoroughly, and the only part my code is failing on lies in this dynamic generation of an object type. Hence why I asked about copying objects. Neither of the solutions posted so far work correctly, by the way. Thank you for your help so far, perhaps this additional information will make it easier to provide advice?

+1  A: 

You could implement something like this:

      Dim p1 As Person = New Person("Tim")
      Dim p2 As Object = CloneObject(p1)
      Dim sameRef As Boolean = p2 Is p1 'false'             


     Private Function CloneObject(ByVal o As Object) As Object
         Dim retObject As Object
         Try
             Dim objType As Type = o.GetType
             Dim properties() As Reflection.PropertyInfo = objType.GetProperties
             retObject = objType.InvokeMember("", System.Reflection.BindingFlags.CreateInstance, Nothing, o, Nothing)
            For Each propertyInfo As PropertyInfo In properties
               If (propertyInfo.CanWrite) Then
                   propertyInfo.SetValue(retObject, propertyInfo.GetValue(o, Nothing), Nothing)
               End If
            Next
         Catch ex As Exception
            retObject = o
         End Try

         Return retObject
       End Function

        Class Person
           Private _name As String
           Public Property Name() As String
        Get
            Return _name
        End Get
        Set(ByVal value As String)
             _name = value
        End Set
          End Property
         Public Sub New()
         End Sub
         Public Sub New(ByVal name As String)
        Me.Name = name
         End Sub
 End Class
Tim Schmelter
That will only work for certain types of objects, for example those that are composed only of properties of simple types.
Doc Brown
You are absolutely right. But because i dont know his real requirement i thought that could be sufficient and gives him the hint where to start. I know this is only a try/error more or less shallow copy. When i'd be the "owner" of that objects i would implement iClonable or make them serializable.
Tim Schmelter
@Tim: no offense, your answer is fine and may be sufficient for the OP - or not (just like mine). We have too less information to see which one suits better.
Doc Brown
+1  A: 

You can't do this in general. And it won't be a good idea, for example, if parameter is of a type which implements the singleton pattern. If parameter is of a type which supports copying, it should implement the ICloneable interface. So, your function could look like this:

Function MyFunc(ByVal parameter As Object) As Object
    Dim cloneableObject As ICloneable = TryCast(parameter, ICloneable)
    If Not cloneableObject Is Nothing Then
        Return cloneableObject.Clone()
    Else
        Return Nothing
    End If
End Function
Doc Brown
A: 

Here's a simple class that will work for most objects (assumes at least .Net 2.0):

Public Class ObjectCloner
    Public Shared Function Clone(Of T)(ByVal obj As T) As T
        Using buffer As MemoryStream = New MemoryStream
            Dim formatter As New BinaryFormatter
            formatter.Serialize(buffer, obj)
            buffer.Position = 0
            Return DirectCast(formatter.Deserialize(buffer), T)
        End Using
    End Function
End Class
Chris Dunaway
The objects it won't work for are objects which are not serializable.
John Saunders
@John - I noticed that and it puzzled me. I thought that the Serializable attribute was only used by the Xml Serializer. But apparently the BinaryFormatter uses it as well.
Chris Dunaway
@Chris: the XML Serializer doesn't use it at all.
John Saunders