Lou Hasketthttp://devlicio.us/blogs/louhaskett/default.aspxenCommunityServer 2008.5 SP1 (Build: 31106.3070)Design Considerations: StructureMap Configuration and Plugin Keyshttp://devlicio.us/blogs/louhaskett/archive/2007/06/26/design-considerations-structuremap-configuration-and-plugin-keys.aspxWed, 27 Jun 2007 04:47:00 GMT40756a8b-6212-4073-9d98-6c26781577de:30505Louis Haskett1115http://devlicio.us/blogs/louhaskett/rsscomments.aspx?PostID=30505http://devlicio.us/blogs/louhaskett/archive/2007/06/26/design-considerations-structuremap-configuration-and-plugin-keys.aspx#commentsI started playing with StructureMap recently. I am struggling with how to design my code's interaction with StructureMap when it comes to the configuration and use of plugin keys. If you have any insights or experience with this, please let me know! 1...(<a href="http://devlicio.us/blogs/louhaskett/archive/2007/06/26/design-considerations-structuremap-configuration-and-plugin-keys.aspx">read more</a>)<img src="http://devlicio.us/aggbug.aspx?PostID=30505" width="1" height="1">c#Dependancy InjectionStructureMapIoCDesign ConsiderationsHow-To: "Cast" between List<T>'shttp://devlicio.us/blogs/louhaskett/archive/2007/06/13/how-to-cast-between-list-t-s.aspxWed, 13 Jun 2007 21:50:00 GMT40756a8b-6212-4073-9d98-6c26781577de:28568Louis Haskett1077http://devlicio.us/blogs/louhaskett/rsscomments.aspx?PostID=28568http://devlicio.us/blogs/louhaskett/archive/2007/06/13/how-to-cast-between-list-t-s.aspx#comments<p><b>Problem</b>:<br>If you've ever tried to cast been list generics, you know that you can't.</p>
<p><b>Example</b>:<br>1. You have two classes Shape and Square, where Square inherits from Shape.</p>
<p>2. You have two generic lists, List&lt;Shape&gt; and List&lt;Square&gt;.</p>
<p>3. List&lt;Square&gt; does not inherit from List&lt;Shape&gt;.&nbsp; So you cannot cast List&lt;Square&gt; to a List&lt;Shape&gt;.&nbsp; It seems intuitive that it should be possible, but it isn't.&nbsp; <br><br>You can find more information <a href="http://64.233.167.104/search?q=cache:0GKl8SNMrxUJ:download.microsoft.com/download/9/8/f/98fdf0c7-2bbd-40d3-9fd1-5a4159fa8044/csharp%25202.0%2520specification_sept_2005.doc%3CA%3E+site:microsoft.com&amp;hl=en&amp;ct=clnk&amp;cd=1&amp;gl=us">here</a>, in the "Constructed Types" section, subsection "Conversions", of the C# Version 2.0 Specification Document.&nbsp; The important part is as follows:</p>
<p>"<font face="Times New Roman" size="3">No special conversions exist between
constructed reference types other than those described in §6. In particular,
unlike array types, constructed reference types do not exhibit “covariant”
conversions.&nbsp; This means that a type </font><font face="Lucida Console" size="2">List&lt;B&gt;</font><font face="Times New Roman" size="3"> has no
conversion (either implicit or explicit) to </font><font face="Lucida Console" size="2">List&lt;A&gt;</font><font face="Times New Roman" size="3"> even if
</font><font face="Lucida Console" size="2">B</font><font face="Times New Roman" size="3"> is derived from </font><font face="Lucida Console" size="2">A</font><font face="Times New Roman" size="3">.&nbsp; Likewise, no conversion exists from
</font><font face="Lucida Console" size="2">List&lt;B&gt;</font><font face="Times New Roman" size="3"> to </font><font face="Lucida Console" size="2">List&lt;object&gt;</font><font face="Times New Roman" size="3">.</font>"&nbsp;</p>
<p>and</p>
<p>"<font face="Times New Roman" size="3">The rationale for this is simple: if a
conversion to </font><font face="Lucida Console" size="2">List&lt;A&gt;</font><font face="Times New Roman" size="3"> is permitted,
then apparently one can store values of type </font><font face="Lucida Console" size="2">A</font><font face="Times New Roman" size="3"> into the list.&nbsp; But this
would break the invariant that every object in a list of type </font><font face="Lucida Console" size="2">List&lt;B&gt;</font><font face="Times New Roman" size="3"> is always a value of type </font><font face="Lucida Console" size="2">B</font><font face="Times New Roman" size="3">, or else unexpected failures
may occur when assigning into collection classes.</font>"&nbsp;</p>
<p><b>Solution</b>:<br>Since you cannot cast between them, you end up having to create a new list, code a for loop, and add the items from one list to the other list.&nbsp; Not a big deal, but i got tired of writing the for loop. :)&nbsp; So here is the utility method i created to do it for me:<br></p>
<p>
<textarea class="c#:nogutter" name="code" rows="25" cols="150">/// &lt;summary&gt;
/// This method adds the items in the first list to the second list.
/// This method is helpful because even when X inherits from Y, List&lt;X&gt; does not inherit from List&lt;Y&gt;, and so you cannot cast between them, only copy.
/// &lt;/summary&gt;
/// &lt;typeparam name="FROM_TYPE"&gt;&lt;/typeparam&gt;
/// &lt;typeparam name="TO_TYPE"&gt;&lt;/typeparam&gt;
/// &lt;param name="listToCopyFrom"&gt;&lt;/param&gt;
/// &lt;param name="listToCopyTo"&gt;&lt;/param&gt;
/// &lt;returns&gt;&lt;/returns&gt;
public static List&lt;TO_TYPE&gt; AddRange &lt;FROM_TYPE, TO_TYPE&gt;( List&lt;FROM_TYPE&gt; listToCopyFrom, List&lt;TO_TYPE&gt; listToCopyTo ) where FROM_TYPE : TO_TYPE
{
// assert
Assert.IsNotNull(listToCopyFrom, "listToCopyFrom");
Assert.IsNotNull(listToCopyTo, "listToCopyTo");
// loop through the list to copy, and
foreach ( FROM_TYPE item in listToCopyFrom )
{
// add items to the copy tolist
listToCopyTo.Add( item );
}
// return the copy to list
return listToCopyTo;
}
</textarea>
</p>
<p>Here is a test i wrote for my method:&nbsp;</p>
<p>
<textarea class="c#:nogutter" name="code" rows="24" cols="130">/// &lt;summary&gt;
/// This method verifies successfully adding items from one List{} to another.
/// &lt;/summary&gt;
[TestMethod]
public void AddRange_Valid()
{
// create a test list
List&lt;TestObjectB&gt; testList = new List&lt;TestObjectB&gt;();
// populate it
testList.Add( new TestObjectB() );
testList.Add( new TestObjectB() );
testList.Add( new TestObjectB() );
// declare a result list
List&lt;TestObjectA&gt; resultList;
// test it
resultList = ListUtility.AddRange( testList, new List&lt;TestObjectA&gt;() );
// assert that the items in the test list and the result list are the same
Assert.AreEqual( testList[0], resultList[0] );
Assert.AreEqual( testList[1], resultList[1] );
Assert.AreEqual( testList[2], resultList[2] );
}
</textarea>
</p>
<p>Ok, Ok, I know its basically just a for loop.&nbsp; But I think the use of a generic method is kind of cool, and it makes my code read a lot better when i have to "cast" a whole bunch of List&lt;&gt;'s.&nbsp; If anyone knows of a better way, please let me know!<br>&nbsp;</p><div style="clear:both;"></div><img src="http://devlicio.us/aggbug.aspx?PostID=28568" width="1" height="1">c#genericshow-tocasting