Cloning objects with events in Visual Basic .NET

The easiest way to clone an object (deep copy) in .NET is to use the serialization functions available:

    Public Shared Function CloneObject(ByVal obj As Object) As Object
        If Not obj Is Nothing Then
            Dim bf = New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
            Dim fs = New System.IO.MemoryStream()
            bf.Serialize(fs, obj)
            fs.Seek(0, System.IO.SeekOrigin.Begin)
            Dim copy = CType(bf.Deserialize(fs), Object)
            Return copy
            Return Nothing
        End If
    End Function

Though the performance is not very good, for occasional operations it will do the job perfectly. However, I was confronted to the following problem: what if there are events inside the class, to which other objects have subscribed? I found several methods (and functions :-)) on various places over the Internet; they basically were:

  • Implement ISerializable yourself (meaning you have to update it each time you modify the class);
  • Disconnect from events (retrieved using Reflection), serialize the object, and then reconnect the events (I could not make this working properly);
  • Implement a serialization surrogate;
  • Implement your events in a separate class that is not serialized;
  • Implement your events in a C# base class.

Plenty of potential solutions, but none of them was good enough for me. So I played around with Reflection and found something that nobody else might have done so far. For a cloning interface that does just a shallow copy, like what MemberwiseClone does, but without event, I wrote this:

    Public Function Clone() As Object Implements System.ICloneable.Clone
        Dim cl = New MyClassName(Me)
        'Here we don't capture events, only normal fields, including non public ones (private, protected...)
        Dim FldInfos() As Reflection.FieldInfo = Me.GetType.GetFields(Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.NonPublic)
        For Each FldInfo As Reflection.FieldInfo In FldInfos
            FldInfo.SetValue(cl, FldInfo.GetValue(Me)) 'For serialization purpose we just need not to have events, so no need to perform a deep copy of the fields.
        Return cl
    End Function

Now if one of your class member is an object with events (or if you want to perform a deep copy), you should call its clone method (to be implemented the same way) when performing the FldInfo.SetValue, like this:

        For Each FldInfo As Reflection.FieldInfo In FldInfos
            If FldInfo.Name <> "MyObjectWithEvents" Then
                FldInfo.SetValue(cl, FldInfo.GetValue(Me)) 'It is not really necessary to clone a possible reference class member here for serialization purpose, we just need not to have events in the clone
                FldInfo.SetValue(cl, Me.MyObjectWithEvents.Clone())
            End If

If you have an object that is for example a dictionary of objects with events, you can call this:

        For Each FldInfo As Reflection.FieldInfo In FldInfos
            If FldInfo.Name <> "MyObjectsWithEventsDictionary" Then
                FldInfo.SetValue(cl, MyLib.CloneObject(FldInfo.GetValue(Me))) 
                FldInfo.SetValue(cl, Me.MyObjectsWithEventsDictionary.ToDictionary(Of String, MyObjectWithEvent)(Function(entry) entry.Key, Function(entry) CType(entry.Value.Clone(), MyObjectWithEvent)))
            End If

Finally, if you intend to use the Clone interface to serialize objects, you should make sure you don’t include class members marked as NonSerialized():

        For Each FldInfo As Reflection.FieldInfo In FldInfos
            If Not FldInfo.IsNotSerialized Then
                FldInfo.SetValue(cl, FldInfo.GetValue(Me))
            End If

I hope this will give you an insight to build something more tailored to your needs. There are other optimizations I can already think of, such as implementing a recursive Clone function where you would just put your original object and a virgin instance of it as a reference, and get a perfect serializable deep copy, whatever the class members and sub class members are! This could become a universal Clone method…

How to sort WordPress posts by modified date instead of published date?

Here is the simple solution. Simply use this:

<?php query_posts($query_string . '&orderby=modified&order=desc'); ?>

before where the Loop checks for posts:

<?php /* If there are any posts: */ 
if (have_posts()) ...

It basically adds a condition to the Loop. Enjoy!

Human rights: are they absolute?

Undoubtedly, human rights represent a way for people to feel safer in a naturally troubled world. This is why the following clip cannot be deemed as harmful and the Erwin Mayer Foundation eagerly supports the message it conveys:

However, except for those who derive them from their religion, mankind shall not forget that these rights do not arise from anything inherent to being human. No absolute principle might be invoked to justify them; though it obviously makes them less appealing and defendable, they are just a contract which clauses have been drafted by a self-proclaimed majority of human societies (who refer to themselves as the United Nations Organizations), and enforced by all those who believe it can improve the common good.

Therefore, it is important to remain careful on any modification of its arbitrary components. In the the video (1:53), I was particularly suprised to read “Copyright” as a human right (item 27). History shows that people can create and share without such a right. Some human rights are dependent on each other and on the context they target, hence you could easily build alternative civilization models with different rights deemed fundamental. “Social security” is another example: beyond the definition problem, what if a civilization has found a better or alternative approach to tackle the same problem, or has not actually considered it as a problem?

Most importantly, human rights, simply because they are rights, have a meaning only when applied to mankind as a group of consenting individuals. A single human, or even a single family, could not incorporate the concept of right, let alone human right, into their understanding of the world.

Human rights make sense because we live in a society, and this is probably the best proof of their not being inherent to each of us. We have the power to define what they are to make our world better, for they are the root, if not the rules, of a civilization.