So as I was working to increase the code coverage for my Commons framework, I found some gnarly edge cases that caused issues in my Cloneable<T> class - specifically dealing with value types. I have since fixed those.
Cloneable<T> is really the guts of my Transactional<T> class, but I figured that it could be useful as a separate class. When you start a transaction, Transactional<T> will use Cloneable<T> to create a copy of the object you want to be transactional. Now historically the way that I've seen this done is to use in-memory binary serialization make a copy.
This is both slow, and consumes unnecessary additional memory. Really, what you want to be able to do is create an instance of an object, and then copy the contents of it's fields from the source to the clone.
In order to create an instance of an object that might not have a parameter-less constructor, I use FormatterServices.GetSafeUninitializedObject(Type type). This allows you to create an instance of an object without calling a constructor. I first learned about this when reviewing how ObjectBuilder works.
Once you've got an instance of the object, you could just use Reflection to copy the contents of the fields, however that is slow. Enter DynamicMethods! DynamicMethods allows you to create a method on the fly, and tack it on to a class. Using Reflection *once* to enumerate what the fields are, I build a method that can copy the fields from the source to the clone by emitting IL (Intermediate Language). When you call the Clone(T source) or ShallowClone(T source) method it calls this dynamically emitted method.
DynamicMethods have a performance profile *almost* identical to that of normal compiled source code. I did a test cloning 1 million instances of a class that had 6 fields - using in-memory binary serialization it took roughly 2 minutes (just shy of it by a few seconds) - using Cloneable<T> it took about 0.5 seconds!!! This bodes well for my Transactional<T> class - creating copies of even complex objects is now a very cheap operation. Is still have to investigate the Code Access Security (CAS) ramifications of emitting the DynamicMethod, but I still think it is a better approach.
I'm still looking to release my Commons framework soon. Code coverage is at 72% now, with Cloneable<T> at 100% covered (I'm sure there are still more edge cases I haven't tested). Once I'm comfortable with the code coverage, I will release it. I'm thinking of releasing it under something like the BSD or MIT license - because I want it to be usable for commercial purposes - but I haven't decided yet.
Any license you would like to see it released under? (and don't say GPL or anything very similar - not going to happen!)