<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>C# test.net</title>
	<atom:link href="http://csharptest.net/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://csharptest.net</link>
	<description>An exploration into testing practices for the C# developer.</description>
	<pubDate>Tue, 08 Jun 2010 21:33:28 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.3</generator>
	<language>en</language>
			<item>
		<title>PasswordHash - how to correctly create a salted password hash</title>
		<link>http://csharptest.net/?p=417</link>
		<comments>http://csharptest.net/?p=417#comments</comments>
		<pubDate>Tue, 08 Jun 2010 21:30:42 +0000</pubDate>
		<dc:creator>rogerk</dc:creator>
		
		<category><![CDATA[Coding]]></category>

		<category><![CDATA[Design]]></category>

		<category><![CDATA[Library]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=417</guid>
		<description><![CDATA[Most people I&#8217;ve seen online compute a simple hash of password + salt for persistence and authentication.  This is the accepted standard in a straight-forward solution:

    byte[] Hash(string password)
    {
        byte[] pass = System.Text.Encoding.UTF8.GetBytes(password);
        [...]]]></description>
			<content:encoded><![CDATA[<p>Most people I&#8217;ve seen online compute a simple hash of password + salt for persistence and authentication.  This is the accepted standard in a straight-forward solution:</p>
<pre class="brush:csharp">
    byte[] Hash(string password)
    {
        byte[] pass = System.Text.Encoding.UTF8.GetBytes(password);
        //Create the salt to use
        byte[] salt = new byte[32];
        new RNGCryptoServiceProvider().GetBytes(salt);
        //Create the hash of password and salt
        HashAlgorithm hashAlgo = new SHA256Managed();
        hashAlgo.TransformBlock(salt, 0, salt.Length, salt, 0);
        hashAlgo.TransformFinalBlock(pass, 0, pass.Length);
        byte[] hash = _hashAlgo.Hash;
        hashAlgo.Initialize();
        //Copy the combined salt + hash to a single array
        byte[] result = new byte[salt.Length + hash.Length];
        Array.Copy(salt, result, salt.Length);
        Array.Copy(hash, 0, result, salt.Length, hash.Length);
        return result;
    }
</pre>
<p>The only deviation i&#8217;ve seen from this is to either use existing data (say a primary key in the database) for the salt, or to &#8216;hide&#8217; the salt at some offset in the result.  Both of these ideas are valid yet amount to not much more than a little obfuscation.  I don&#8217;t recommend it.</p>
<p>Now if you REALLY want to secure your passwords and/or protect against brute force attacks there is another approach.  The approach is quite common in generating crypto keys from passwords but can just as easily be used for hashing the password.  The idea/concept is expressed in RFC2898 by the introduction of the iteration count.  By introducing this into the password hash we increase the computational complexity required to test a password by several orders of magnitude.  The straight-forward way of achieving this in the BCL is as follows:</p>
<pre class="brush:csharp">
    byte[] Hash(string password)
    {
        //Create the salt to use
        byte[] salt = new byte[20];
        new RNGCryptoServiceProvider().GetBytes(salt);
        //Combine the salt with the iteration-count
        byte[] iterationBytes = BitConverter.GetBytes(1010);
        byte[] iterationSalt = (byte[])salt.Clone();
        for (int i = 0; i < iterationSalt.Length; i++)
            iterationSalt[i] ^= iterationBytes[i % iterationBytes.Length];
        //Create the hash of password and salt
        DeriveBytes deriveBytes = new Rfc2898DeriveBytes(password, iterationSalt, 1010);
        byte[] hash = deriveBytes.GetBytes(20);
        //Copy the combined salt + hash to a single array
        byte[] result = new byte[salt.Length + hash.Length];
        Array.Copy(salt, result, salt.Length);
        Array.Copy(hash, 0, result, salt.Length, hash.Length);
        return result;
    }
</pre>
<p>This will work very well but will be more costly to calculate than the first algorithm.  I would not want to use this in a system that verifies passwords on every request (i.e. Basic Auth over SSL); however, for token-auth systems this will prove much more durable to brute force attacks. By combining the iteration count to the salt (or key) you make the attacker repeat the entire iteration sequence for each iteration count attempted.  This makes it significantly more difficult for them to steal the password hashs and crack the passwords without also stealing the software or otherwise knowing the iteration count.  Even knowing the iteration count it&#8217;s now much more expensive to compute each attempt at matching an entry in their password dictionary.</p>
<p>Recently I&#8217;ve added the <a href="http://code.google.com/p/csharptest-net/source/browse/trunk/src/Library/Crypto/PasswordHash.cs">PasswordHash</a> class to wrap up some of this behavior.  Note that this class does not combine the iteration count with the salt, yet still provides significant security benefits over a simple hash.  </pre>
]]></content:encoded>
			<wfw:commentRss>http://csharptest.net/?feed=rss2&amp;p=417</wfw:commentRss>
		</item>
		<item>
		<title>HashDerivedBytes - replacing Rfc2898DeriveBytes, but why?</title>
		<link>http://csharptest.net/?p=413</link>
		<comments>http://csharptest.net/?p=413#comments</comments>
		<pubDate>Tue, 08 Jun 2010 20:32:36 +0000</pubDate>
		<dc:creator>rogerk</dc:creator>
		
		<category><![CDATA[Coding]]></category>

		<category><![CDATA[Library]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=413</guid>
		<description><![CDATA[So recently I&#8217;ve been working heavily with some of the cryptography stuff in .Net and adding a large amount of it to my open source library.  One of the many things I needed to perform was simply encrypting and decrypting a piece of data with a password.
It seems everyone out there is using Rfc2898DeriveBytes [...]]]></description>
			<content:encoded><![CDATA[<p>So recently I&#8217;ve been working heavily with some of the cryptography stuff in .Net and adding a large amount of it to my open source library.  One of the many things I needed to perform was simply encrypting and decrypting a piece of data with a password.</p>
<p>It seems everyone out there is using Rfc2898DeriveBytes by now and not using the older PasswordDeriveBytes.  So it&#8217;s use is simple enough, construct it with a password, ask it for a number of bytes, and off you go.  When things get interesting is correctly providing salt to the derived bytes algorithm.  I didn&#8217;t want to deal with this all over my code and thus built the <a href="http://code.google.com/p/csharptest-net/source/browse/trunk/src/Library/Crypto/PasswordKey.cs">PasswordKey</a> class.  It auto-magically prepends the salt to the stream when encrypting data.  When decrypting data it reads the salt, generates the key, and then decrypts the data.</p>
<p>At first everything went well, it seemed to work and, as per my norm, I quickly got my unit tests pounding on the implementation.  Somewhere along the way though I must have used the Rfc2898DeriveBytes class in a way that was not expected as when I began running in release (optimized) mode I started seeing strange results.  The tests were generating 32-bit keys with the same password, iteration, and salt combinations and were generating different keys?  The funnest part was they only differed after the first 20 bytes.  How could this be?  If the input was wrong there is almost no likelihood the first 20 bytes would be the same, so how did I fail?  I looked and looked, googled and googled some more.  Read nearly every line of code in the class using Reflector.Net, nothing.  Still to this day I don&#8217;t know why it&#8217;s breaking, I do know I can get two identical 20-byte keys, or two identical 40-byte keys, but I still get two different 32-byte keys&#8230; What should I do? Well I came up with two possible solutions:</p>
<p>1. The first &#8216;fix&#8217; for this issue resulted in the <a href="http://code.google.com/p/csharptest-net/source/browse/trunk/src/Library/Crypto/PBKDF2.cs">PBKDF2</a> class that derives from Rfc2898DeriveBytes.  Then by overriding the GetBytes() method I can always pass a value of 20 to the actual GetBytes() base method:</p>
<pre class="brush:csharp">
    public override byte[] GetBytes(int cb)
    {
        byte[] buffer = new byte[cb];
        for (int i = 0; i &lt; cb; i += 20)
        {
            int step = Math.Min(20, cb - i);
            Array.Copy(base.GetBytes(20), 0, buffer, i, step);
        }
        return buffer;
    }
</pre>
<p>2. Then I started debating the value of using a 20-byte hash to generate 32 bytes of data.  Seemed like this algorithm was just as applicable with any size hash right?  Sure enough&#8230;  So the second, and finally preferred solution was to recreate the algorithm with a variable hash algorithm.  This gave birth to the <a href="http://code.google.com/p/csharptest-net/source/browse/trunk/src/Library/Crypto/HashDerivedBytes.cs">HashDerivedBytes&lt;THash></a> implementation which accepts THash to be any HMAC (Keyed hash) derived implementation.  With this I&#8217;m able to force the use of the managed SHA256 hash routine and elevate the iterations by nearly an order of magnitude without substantial performance loss.  In the end I&#8217;m pleased with the implementation and can verify it&#8217;s compliance with the original algorithm by comparing it&#8217;s output using SHA1 with that of the original Rfc2898 and produce compatible results.</p>
<p>Anyway if you have problems with the Rfc2898DeriveBytes class I&#8217;d like to hear from you just to make sure I&#8217;m not crazy.  And now you know of two possible solutions if you do have problems ;)</p>
]]></content:encoded>
			<wfw:commentRss>http://csharptest.net/?feed=rss2&amp;p=413</wfw:commentRss>
		</item>
		<item>
		<title>Version 1.10.607.213 released</title>
		<link>http://csharptest.net/?p=403</link>
		<comments>http://csharptest.net/?p=403#comments</comments>
		<pubDate>Tue, 08 Jun 2010 18:23:44 +0000</pubDate>
		<dc:creator>rogerk</dc:creator>
		
		<category><![CDATA[Home]]></category>

		<category><![CDATA[Library]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=403</guid>
		<description><![CDATA[Changes in this version:

Library.Crypto namespace was added with a fairly complete cryptography API (at least what I needed) including:

Added Library.Crypto.WhirlpoolManaged a managed implementation of the whirlpool hash function.
Added Library.Crypto.Password to wrap up the complexities of using a password for authentication and/or encryption.


Library.IO namespace was added to include several new stream derivations including:

Added Library.IO.SegmentedMemoryStream for memory [...]]]></description>
			<content:encoded><![CDATA[<p>Changes in this version:</p>
<ul>
<li>Library.Crypto namespace was added with a fairly complete cryptography API (at least what I needed) including:
<ul>
<li>Added Library.Crypto.<a href="http://code.google.com/p/csharptest-net/source/browse/trunk/src/Library/Crypto/WhirlpoolManaged.cs">WhirlpoolManaged</a> a managed implementation of the <a href="http://en.wikipedia.org/wiki/Whirlpool_(cryptography)">whirlpool hash function</a>.</li>
<li>Added Library.Crypto.<a href="http://code.google.com/p/csharptest-net/source/browse/trunk/src/Library/Crypto/Password.cs">Password</a> to wrap up the complexities of using a password for authentication and/or encryption.</li>
</ul>
</li>
<li>Library.IO namespace was added to include several new stream derivations including:
<ul>
<li>Added Library.IO.<a href="http://code.google.com/p/csharptest-net/source/browse/trunk/src/Library/IO/SegmentedMemoryStream.cs">SegmentedMemoryStream</a> for memory streaming while avoiding LOH allocations.</li>
<li>Added Library.IO.<a href="http://code.google.com/p/csharptest-net/source/browse/trunk/src/Library/IO/TempFile.cs">TempFile</a> to manage temp files and remove them when disposed.</li>
<li>Added Library.IO.<a href="http://code.google.com/p/csharptest-net/source/browse/trunk/src/Library/IO/ReplaceFile.cs">ReplaceFile</a> to transact replacing a file.</li>
</ul>
</li>
<li>Library.Html namespace was added to help with manipulation of html and xhtml:
<ul>
<li>Added Library.Html.<a href="http://code.google.com/p/csharptest-net/source/browse/trunk/src/Library/Html/XhtmlValidation.cs">XhtmlValidation</a> will use the w3c xhtml 1.0 DTDs to validate xhtml files.</li>
<li>Added Library.Html.<a href="http://code.google.com/p/csharptest-net/source/browse/trunk/src/Library/Html/HtmlLightDocument.cs">HtmlLightDocument</a> to a provide fast DOM parsing of HTML using regular expressions.</li>
<li>Added Library.Html.<a href="http://code.google.com/p/csharptest-net/source/browse/trunk/src/Library/Html/XmlLightDocument.cs">XmlLightDocument</a> to a provide fast DOM parsing of XML using regular expressions.</li>
</ul>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://csharptest.net/?feed=rss2&amp;p=403</wfw:commentRss>
		</item>
		<item>
		<title>JiraSVN 64-bit installer, Finally!</title>
		<link>http://csharptest.net/?p=326</link>
		<comments>http://csharptest.net/?p=326#comments</comments>
		<pubDate>Tue, 08 Jun 2010 16:49:45 +0000</pubDate>
		<dc:creator>rogerk</dc:creator>
		
		<category><![CDATA[Home]]></category>

		<category><![CDATA[JiraSvn]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=326</guid>
		<description><![CDATA[This plugin should now be functional on 64-bit installations of TortoiseSVN, use the following installation:
http://code.google.com/p/csharptest-net/downloads/detail?name=SvnPluginInstall-x64.msi
Let me know if you have any difficulties.
]]></description>
			<content:encoded><![CDATA[<p>This plugin should now be functional on 64-bit installations of TortoiseSVN, use the following installation:</p>
<p><a href="http://code.google.com/p/csharptest-net/downloads/detail?name=SvnPluginInstall-x64.msi">http://code.google.com/p/csharptest-net/downloads/detail?name=SvnPluginInstall-x64.msi</a></p>
<p>Let me know if you have any difficulties.</p>
]]></content:encoded>
			<wfw:commentRss>http://csharptest.net/?feed=rss2&amp;p=326</wfw:commentRss>
		</item>
		<item>
		<title>//funny&#8230;</title>
		<link>http://csharptest.net/?p=395</link>
		<comments>http://csharptest.net/?p=395#comments</comments>
		<pubDate>Mon, 10 May 2010 15:49:37 +0000</pubDate>
		<dc:creator>rogerk</dc:creator>
		
		<category><![CDATA[Coding]]></category>

		<category><![CDATA[Home]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=395</guid>
		<description><![CDATA[Recently I was killing time on stackoverflow and found this question:
What is the best comment in source code you have ever encountered?
There are a lot of great quotes in there.  If you haven&#8217;t seen it already it worth a read when you want to kill some time.  I&#8217;d also add my own to [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I was killing time on stackoverflow and found this question:</p>
<blockquote><p><a href="http://stackoverflow.com/questions/184618/">What is the best comment in source code you have ever encountered?</a></p></blockquote>
<p>There are a lot of great quotes in there.  If you haven&#8217;t seen it already it worth a read when you want to kill some time.  I&#8217;d also add my own to the list:</p>
<pre class="brush:c#">
    // The DM warns the following encounter is EL25 and should only be attempted
    // by Epic level parties.
</pre>
]]></content:encoded>
			<wfw:commentRss>http://csharptest.net/?feed=rss2&amp;p=395</wfw:commentRss>
		</item>
		<item>
		<title>Implementing a generic deep-clone for C# objects</title>
		<link>http://csharptest.net/?p=390</link>
		<comments>http://csharptest.net/?p=390#comments</comments>
		<pubDate>Sat, 08 May 2010 21:15:55 +0000</pubDate>
		<dc:creator>rogerk</dc:creator>
		
		<category><![CDATA[Coding]]></category>

		<category><![CDATA[Home]]></category>

		<category><![CDATA[Library]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=390</guid>
		<description><![CDATA[As promised in the previous post &#8220;How to implement a generic Shallow-Clone for an object in C#&#8221; this will demonstrate deep-cloning objects that don&#8217;t explicitly support the behavior.
Before I continue I will again state that I don&#8217;t recommend this approach.  It will be many times slower than a properly implemented Clone() and can cause [...]]]></description>
			<content:encoded><![CDATA[<p>As promised in the previous post &#8220;<a href="http://csharptest.net/?p=372">How to implement a generic Shallow-Clone for an object in C#</a>&#8221; this will demonstrate deep-cloning objects that don&#8217;t explicitly support the behavior.</p>
<p>Before I continue I will again state that I don&#8217;t recommend this approach.  It will be many times slower than a properly implemented Clone() and can cause rather strange side-effects.  For instance, deep-cloning a tree of objects that hold reference to a singleton service class would result in cloning that singleton.  This problem simply stems from the fact that no generic code can have enough knowledge about the internal structure of classes to be able to accurately guess when and when not to clone a member reference.  Thus if you going to code the logic of which members to clone or not, it&#8217;s best done in the objects themselves and is the primary reason I say a generic deep clone is a bad idea.  Even if you don&#8217;t currently have a reference to a singleton now, what happens when someone adds one to the object graph?  How will your application behave?</p>
<p>So with this established as a bad idea it is with great trepidation that I demonstrate how to achieve this.  To start with let&#8217;s demonstrate usage in the Library:</p>
<pre class="brush:c#">
using CSharpTest.Net.Cloning;

    //Uses serialization API if available or member-wise if non-serializable
    using (ObjectCloner cloner = new SerializerClone())
        fooCopy = cloner.Clone(foo);
    // 3.5 can use extension method instead of the code above:
    fooCopy = foo.DeepClone();

    //To ignore serialization routines, use the following:
    using (ObjectCloner cloner = new MemberwiseClone())
        fooCopy = cloner.Clone(foo);
</pre>
<p>Implementation details, there are not a lot to share, you can see the source easily enough at:<br />
<a href="http://code.google.com/p/csharptest-net/source/browse/#svn/trunk/src/Library/Cloning">http://code.google.com/p/csharptest-net/source/browse/#svn/trunk/src/Library/Cloning</a></p>
<p>There are a few things worth pointing out.  The <a href="http://code.google.com/p/csharptest-net/source/browse/trunk/src/Library/Cloning/ObjectCloner.cs">ObjectCloner</a> provides a base-class that handles the object graph and a few well-known types (delegates, arrays, primitives, etc).  Derived from this is the <a href="http://code.google.com/p/csharptest-net/source/browse/trunk/src/Library/Cloning/MemberwiseClone.cs">MemberwiseClone</a> class which provides a basic &#8216;memory copy&#8217; type of copy operation.  Again deriving from this is the <a href="http://code.google.com/p/csharptest-net/source/browse/trunk/src/Library/Cloning/SerializerClone.cs">SerializerClone</a> which implements a pseudo serialization routine by attempting to mimic the .Net serializer&#8217;s default implementation.  This results in three possible types of copy operations:</p>
<p>1. If ISerializable is implemented it will be used, allowing customization of the copy.<br />
2. If [Serializable] decoration is present the FormatterServices.GetSerializableMembers is used to allow respecting the [NonSerialized] attribute.<br />
3. Lastly if the object doesn&#8217;t support serialization a straight member-by-member copy is made.</p>
<p>This continues throughout the object graph until all object members have been copied into the new tree.  Finally if appropriate calls to IDeserializationCallback will be made just prior to the top-level instance being returned.</p>
<p>One thing of note is that the object graph is made public to allow preventing some instances from being copied.  For instance if you want to copy foo&#8217;s complete object graph except for any instances of &#8216;bar&#8217; then you would do this:</p>
<pre class="brush:c#">
using CSharpTest.Net.Cloning;

    using (ObjectCloner cloner = new SerializerClone())
    {
        // maps instances of bar to itself:
        cloner.Graph.Add(bar, bar);
        fooCopy = cloner.Clone(foo);
    }
</pre>
]]></content:encoded>
			<wfw:commentRss>http://csharptest.net/?feed=rss2&amp;p=390</wfw:commentRss>
		</item>
		<item>
		<title>Visual Studio 2010 time to upgrade&#8230;???</title>
		<link>http://csharptest.net/?p=381</link>
		<comments>http://csharptest.net/?p=381#comments</comments>
		<pubDate>Fri, 23 Apr 2010 16:54:29 +0000</pubDate>
		<dc:creator>rogerk</dc:creator>
		
		<category><![CDATA[Design]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=381</guid>
		<description><![CDATA[Well just got the release version of VS2010 installed and all I can say is &#8220;OMG&#8221;.  Not an OMG as in &#8220;OMG that is so cool!&#8221;, but more like an &#8220;OMG, are you serious?&#8221;.
&#160;
Several things are standing out as wickedly wrong before I even open a solution&#8230;
&#160;
My hardware is no longer sufficient.  I&#8217;m running on an [...]]]></description>
			<content:encoded><![CDATA[<p>Well just got the release version of VS2010 installed and all I can say is &#8220;OMG&#8221;.  Not an OMG as in &#8220;OMG that is so cool!&#8221;, but more like an &#8220;OMG, are you serious?&#8221;.<br />
&nbsp;<br />
Several things are standing out as wickedly wrong before I even open a solution&#8230;<br />
&nbsp;<br />
My hardware is no longer sufficient.  I&#8217;m running on an HP Pavilion notebook about 2yrs old. Running a dual-core 2.2ghz (3gb RAM) with Vista SP2 32-bit.  Just moving my mouse through menus and around the UI, dragging windows, etc is painful and eating 30-50% of my CPU.  Now I know it&#8217;s not stellar machine but my mouse jumping several inches at a time is crazy unusable.  Since I don&#8217;t time or money to buy new hardware right now I&#8217;ve disable the Vista Areo and reverted to the Windows 2000 look and feel.  Things are moving much better now&#8230; Almost usable if ugly.  The scrolling speed of source code is still nasty slow.  So word to the wise if you scoring below 3.0 on the &#8220;Windows Experience Index&#8221; for &#8220;3D business and gaming graphics performance&#8221; your probably in for a hardware update.<br />
&nbsp;<br />
Tabbed documents, I hate them.  Unfortunately for me Microsoft is cramming another user experience change down my throat.  Like that @#^*ing &#8216;Ribbon bars&#8217; interface in Office there is no way to turn it off in VS2010.  (I actually quit using MS Office and switched to OOo to avoid ribbons).  It&#8217;s cool that you make the source window float out of the app, but I&#8217;m still going to desperately miss the good-old-fashioned MDI view.<br />
&nbsp;<br />
I&#8217;m sure that over the comming days, weeks, and years I&#8217;ll find much more to hate and love about about VS2010, but so far I&#8217;m not a fan. I guess I&#8217;ll go take some time to get to know VS2010 a little better and see if my initial reaction changes.  I hate to think what the next GUI design change from MS will entail for me &#8230; I guess I&#8217;m just old and set in my ways.<br />
&nbsp;<br />
LOL, at least I&#8217;m not the only one: <a href="http://social.msdn.microsoft.com/Forums/en/vseditorprerelease/thread/78f44eb2-96dd-47eb-a7d0-c9e3fdf396d0">What happened to MDI capability in the editor?</a></p>
]]></content:encoded>
			<wfw:commentRss>http://csharptest.net/?feed=rss2&amp;p=381</wfw:commentRss>
		</item>
		<item>
		<title>Version 1.10.420.164 released</title>
		<link>http://csharptest.net/?p=378</link>
		<comments>http://csharptest.net/?p=378#comments</comments>
		<pubDate>Wed, 21 Apr 2010 02:00:59 +0000</pubDate>
		<dc:creator>rogerk</dc:creator>
		
		<category><![CDATA[Home]]></category>

		<category><![CDATA[Library]]></category>

		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=378</guid>
		<description><![CDATA[Changes in this version:

CSBuild initial release - a command-line compilation utility that drives MSBuild to compile designated project files.  
Added Library.Cloning namespace to support deep-object cloning of any object using either memberwize or serializable copy.
Added Library.Collections.ReadOnlyList to provide a read-only collection interface and implementation.
Added Library.Collections.OrdinalList to provide a collection of integers stored as a [...]]]></description>
			<content:encoded><![CDATA[<p>Changes in this version:</p>
<ul>
<li>CSBuild initial release - a command-line compilation utility that drives MSBuild to compile designated project files.  </li>
<li>Added Library.Cloning namespace to support deep-object cloning of any object using either memberwize or serializable copy.</li>
<li>Added Library.Collections.ReadOnlyList to provide a read-only collection interface and implementation.</li>
<li>Added Library.Collections.OrdinalList to provide a collection of integers stored as a bit-array that can be operated on as a set (intersect/union/etc).</li>
<li>Added Library.Collections.SetList to provide a generic collection of that can be operated on as a set (intersect/union/etc).</li>
<li>CommandInterpreter can now read SET operations from stream, also added an IgnoreMember attribute.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://csharptest.net/?feed=rss2&amp;p=378</wfw:commentRss>
		</item>
		<item>
		<title>How to implement a generic Shallow-Clone for an object in C#</title>
		<link>http://csharptest.net/?p=372</link>
		<comments>http://csharptest.net/?p=372#comments</comments>
		<pubDate>Thu, 15 Apr 2010 00:02:04 +0000</pubDate>
		<dc:creator>rogerk</dc:creator>
		
		<category><![CDATA[Coding]]></category>

		<category><![CDATA[Home]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=372</guid>
		<description><![CDATA[This implementation makes heavy use of the FormatterServices object used by serialization:
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatterservices_members.aspx
It provides several helpful methods in this case that are aware of custom serialization options like [NonSerialized].  In the case of an object not being marked [Serializable] you have to create field list manually.  Here is an example shallow object clone:

using System.Runtime.Serialization;
using [...]]]></description>
			<content:encoded><![CDATA[<p>This implementation makes heavy use of the FormatterServices object used by serialization:</p>
<p><a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatterservices_members.aspx">http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatterservices_members.aspx</a></p>
<p>It provides several helpful methods in this case that are aware of custom serialization options like [NonSerialized].  In the case of an object not being marked [Serializable] you have to create field list manually.  Here is an example shallow object clone:</p>
<pre class="brush:c#">
using System.Runtime.Serialization;
using System.Reflection;

    static class Clonable
    {
        public static T Clone&lt;T>(this T instance)
        {
            object copy;
            Type type = instance.GetType();

            if (instance is ICloneable)
                return (T)((ICloneable)instance).Clone();

            List&lt;MemberInfo> fields = new List&lt;MemberInfo>();
            if (type.GetCustomAttributes(typeof(SerializableAttribute), false).Length == 0)
            {
                Type t = type;
                while (t != typeof(Object))
                {
                    fields.AddRange(t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
                    t = t.BaseType;
                }
            }
            else
                fields.AddRange(FormatterServices.GetSerializableMembers(instance.GetType()));

            copy = FormatterServices.GetUninitializedObject(instance.GetType());
            object[] values = FormatterServices.GetObjectData(instance, fields.ToArray());
            FormatterServices.PopulateObjectMembers(copy, fields.ToArray(), values);

            return (T)copy;
        }
    }
</pre>
<p>As with anything, use this carefully.  This method run against some objects will cause native handles to be copied and can then lead to application crashes in unmanaged code.</p>
<p>If you need a deep clone things get a lot more complicated.  I don&#8217;t recommend it; rather you should insist that objects are decorated with [Serialiable] and simply use serialization to copy the object.  That being said, I will post a working deep-clone as a follow up to this post.</p>
]]></content:encoded>
			<wfw:commentRss>http://csharptest.net/?feed=rss2&amp;p=372</wfw:commentRss>
		</item>
		<item>
		<title>Addicted to video games?</title>
		<link>http://csharptest.net/?p=369</link>
		<comments>http://csharptest.net/?p=369#comments</comments>
		<pubDate>Fri, 05 Mar 2010 18:02:21 +0000</pubDate>
		<dc:creator>rogerk</dc:creator>
		
		<category><![CDATA[Home]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=369</guid>
		<description><![CDATA[Sorry to misappropriate my blog for a moment but I had to post this.  
Hi, my name is Roger and I&#8217;ve been video game free for 8 years.  In that time I&#8217;ve fallen off the wagon a few times; however, they were brief episodes.  As a recovering gameaholic this video really strikes [...]]]></description>
			<content:encoded><![CDATA[<p>Sorry to misappropriate my blog for a moment but I had to post this.  </p>
<p>Hi, my name is Roger and I&#8217;ve been video game free for 8 years.  In that time I&#8217;ve fallen off the wagon a few times; however, they were brief episodes.  As a recovering gameaholic this video really strikes home for me.  The message to gamers is spot-on IMO, I just wish those still addicted could truly &#8216;hear&#8217; what he is saying.  See for yourself:</p>
<p><a href="http://www.youtube.com/watch?v=YKBRG_QgEAM">http://www.youtube.com/watch?v=YKBRG_QgEAM</a><br />
<object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/YKBRG_QgEAM&#038;hl=en_US&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/YKBRG_QgEAM&#038;hl=en_US&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object></p>
<p>Aside from the message alone, I also want to complement the author on the quality of the video.  He is obviously talented at more than just button mashing.</p>
]]></content:encoded>
			<wfw:commentRss>http://csharptest.net/?feed=rss2&amp;p=369</wfw:commentRss>
		</item>
	</channel>
</rss>
