<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>marklio - Technical</title>
    <link>http://www.marklio.com/marklio/</link>
    <description>better than the original</description>
    <image>
      <url>http://photos1.flickr.com/buddyicons/12488026@N00.jpg?1105565509</url>
      <title>marklio - Technical</title>
      <link>http://www.marklio.com/marklio/</link>
    </image>
    <language>en-us</language>
    <copyright>Mark Miller</copyright>
    <lastBuildDate>Sat, 13 Mar 2010 03:14:59 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.3.9074.18820</generator>
    <managingEditor>mark@marklio.com</managingEditor>
    <webMaster>mark@marklio.com</webMaster>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=ecc34c3c-be44-4422-86b7-900900e451f9</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,ecc34c3c-be44-4422-86b7-900900e451f9.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,ecc34c3c-be44-4422-86b7-900900e451f9.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=ecc34c3c-be44-4422-86b7-900900e451f9</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
This post is intended to fill a gap in the current MSDN documentation for this attribute
(<a title="http://msdn.microsoft.com/en-us/library/bbx34a2h(VS.100).aspx" href="http://www.marklio.com/marklio/ct.ashx?id=ecc34c3c-be44-4422-86b7-900900e451f9&amp;url=http%3a%2f%2fmsdn.microsoft.com%2fen-us%2flibrary%2fbbx34a2h(VS.100).aspx" target="_blank">http://msdn.microsoft.com/en-us/library/bbx34a2h(VS.100).aspx</a>). 
This gap should be filled by the time .NET 4 ships.
</p>
        <p>
There is alot of confusion about what the useLegacyV2RuntimeActivationPolicy attribute
does.  Most often, it is used to allow a pre-v4 mixed-mode assembly to load in
v4.  In that context, the name makes very little sense.  Below is an explanation
I’ve provided to people internally that explains the attribute in the context for
which it was named.  This should give people a better idea of what it does, as
well as understand some of the subtlies of in-proc SxS.
</p>
        <p>
Ultimately, this attribute has to do with the behavior of the “legacy shim APIs”. 
You can think of these as encompassing several categories of CLR activation: 
</p>
        <ul>
          <li>
CorBindToRuntimeEx and friends - This includes most of the flat exports of mscoree.dll
defined in mscoree.h (GetCORSystemDirectory, GetCORVersion, LoadLibraryShim, etc).
Note, this also includes the strong name APIs defined in strongname.h) 
</li>
          <li>
Pre-v4 COM activation – This includes CoCreateInstance of a CLSID (or type identifier)
whose latest registration is against a pre-v4 runtime version. Note this includes
both the “new” operator on such a co-class from managed code, or the result of Activator.CreateInstance
against a type created by Type.GetTypeFromCLSID on such a CLSID. 
</li>
          <li>
Pre-v4 IJW (mixed mode) activation – For example, calling into a native export on
such an assembly 
</li>
          <li>
Native activation of a native runtime-provided COM CLSID – Such as CoCreateInstance
on ICLRRuntimeHost’s CLSID 
</li>
          <li>
Native activation of a managed framework CLSID – Such as CoCreateInstance on System.ArrayList’s
CLSID (extremely rare)</li>
        </ul>
        <p>
All these have a “single runtime per process” view of the world, so we try to make
those codepaths believe they still exist in that world by “unifying” the version that
they see.  After a given version has been chosen by one of these codepaths, that’s
the version that all of them see for the remainder of the process lifetime. 
Additionally, all of these activation paths had some kind of roll-forward semantics
associated with them.  We “cap” those semantics at v2, meaning by default none
of these codepaths see v4 at all.  This allows us to claim that installing v4
is “non-impactful”.  It should not change the behavior of existing components
when installed. (Note that this has the interesting side-effect of a v4 only machine
appearing to have no runtimes installed at all via these codepaths.)
</p>
        <p>
This is all well and good until someone WANTS those codepaths to see v4.  Rolling
a v2 managed app forward to v4 using a config (without the attribute) works just fine,
unless that app also expects interaction with these “legacy” codepaths to be associated
with the current runtime (v4).  For instance, a p/Invoke to GetCorSystemDirectory
in order to construct a path to Fusion.dll (please don’t do that, BTW) will give you
v2’s fusion.dll.  COM activation of a managed COM object will prefer the runtime
it was built against rather than load into the current runtime (meaning you may be
dealing with interop rather than a concrete CLR type). That may work, and it may not,
depending on what you’re doing. 
</p>
        <p>
The useLegacyV2RuntimeActivationPolicy attribute basically lets you say, “I have some
dependencies on the legacy shim APIs.  Please make them work the way they used
to with respect to the chosen runtime.”  In that context, hopefully the name
makes more sense to you. It is *<b>mostly</b>* equivalent to calling CorBindToRuntimeEx
using the full version string for v4.  We also have a <a href="http://www.marklio.com/marklio/ct.ashx?id=ecc34c3c-be44-4422-86b7-900900e451f9&amp;url=http%3a%2f%2fmsdn.microsoft.com%2fen-us%2flibrary%2fee426955(VS.100).aspx" target="_blank">method
in our new shim APIs</a> to do this programmatically, the difference being that in
a config file, it can be done declaratively, which is useful for a host that uses
config files to determine which runtime to load plugins into. (the attributes value
(or lack of value) is conveyed back to a host via the pdwConfigFlags parameter of <a href="http://www.marklio.com/marklio/ct.ashx?id=ecc34c3c-be44-4422-86b7-900900e451f9&amp;url=http%3a%2f%2fmsdn.microsoft.com%2fen-us%2flibrary%2fdd380612(VS.100).aspx" target="_blank">ICLRMetaHostPolicy::GetRequestedRuntime</a>) 
</p>
        <p>
One of the big reasons people need to do this is if they have a dependency on a pre-v4
IJW assembly.  By default, we can’t allow those to load into v4*.  Putting
this attribute in your config allows this to happen. 
</p>
        <p>
Why don’t we make this the default behavior? You might argue that this behavior is
more compatible, and makes porting code from previous versions much easier. If you’ll
recall, this can’t be the default behavior because it would make installation of v4
impactful, which can break existing apps installed on your machine. 
</p>
        <p>
Well, why don’t we make this the default behavior for v4 managed apps?  Well,
that is precisely the behavior we had for beta 1.  As we started trying to explain
the behavior to people, we found it was very difficult to explain how these legacy
codepaths worked.  We ultimately decided that making the behavior consistent
was better.  The example that ultimately convinced me we had made the right choice
was that the behavior of a library would change based on whether it was hosted by
a native process or a managed one.  That seemed really bad to me. 
</p>
        <p>
You might say, “Why shouldn’t I just set this for every app I have?” Well, the downside
of this attribute is that it turns off in-proc SxS with pre-v4 runtimes.  It
locks them out of the process.  This may not matter to your scenario.  If
you look at some of the runtime tools, they are using this attribute.  Even Visual
Studio uses this attribute.  Don’t just blindly use it though.  If you'
find yourself needing it in something other than a migration aid, or for loading pre-v4
mixed-mode assemblies (which we hope becomes more rare moving forward as people start
updating the interesting mixed-mode binaries out there), I’d like to know about it. 
Leave me a comment! 
</p>
        <p>
Hopefully, you’ve got a better handle on exactly what this attribute means, and can
make a more informed decision about when it is appropriate to use. 
</p>
        <p>
          <em>*There are many engineering challenges around in-proc SxS and IJW assemblies. 
Currently, pre-v4 IJW assemblies can only load into the runtime that is associated
with the “legacy shim APIs”.  But any given IJW assembly (regardless of version)
may only be loaded into a single runtime per process at this time.</em>
        </p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=ecc34c3c-be44-4422-86b7-900900e451f9" />
      </body>
      <title>What is useLegacyV2RuntimeActivationPolicy for?</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,ecc34c3c-be44-4422-86b7-900900e451f9.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,ecc34c3c-be44-4422-86b7-900900e451f9.aspx</link>
      <pubDate>Sat, 13 Mar 2010 03:14:59 GMT</pubDate>
      <description>&lt;p&gt;
This post is intended to fill a gap in the current MSDN documentation for this attribute
(&lt;a title="http://msdn.microsoft.com/en-us/library/bbx34a2h(VS.100).aspx" href="http://www.marklio.com/marklio/ct.ashx?id=ecc34c3c-be44-4422-86b7-900900e451f9&amp;amp;url=http%3a%2f%2fmsdn.microsoft.com%2fen-us%2flibrary%2fbbx34a2h(VS.100).aspx" target="_blank"&gt;http://msdn.microsoft.com/en-us/library/bbx34a2h(VS.100).aspx&lt;/a&gt;).&amp;nbsp;
This gap should be filled by the time .NET 4 ships.
&lt;/p&gt;
&lt;p&gt;
There is alot of confusion about what the useLegacyV2RuntimeActivationPolicy attribute
does.&amp;nbsp; Most often, it is used to allow a pre-v4 mixed-mode assembly to load in
v4.&amp;nbsp; In that context, the name makes very little sense.&amp;nbsp; Below is an explanation
I’ve provided to people internally that explains the attribute in the context for
which it was named.&amp;nbsp; This should give people a better idea of what it does, as
well as understand some of the subtlies of in-proc SxS.
&lt;/p&gt;
&lt;p&gt;
Ultimately, this attribute has to do with the behavior of the “legacy shim APIs”.&amp;nbsp;
You can think of these as encompassing several categories of CLR activation: 
&lt;ul&gt;
&lt;li&gt;
CorBindToRuntimeEx and friends - This includes most of the flat exports of mscoree.dll
defined in mscoree.h (GetCORSystemDirectory, GetCORVersion, LoadLibraryShim, etc).
Note, this also includes the strong name APIs defined in strongname.h) 
&lt;li&gt;
Pre-v4 COM activation – This includes CoCreateInstance of a CLSID (or type identifier)
whose latest registration is against a pre-v4 runtime version. Note this includes
both the “new” operator on such a co-class from managed code, or the result of Activator.CreateInstance
against a type created by Type.GetTypeFromCLSID on such a CLSID. 
&lt;li&gt;
Pre-v4 IJW (mixed mode) activation – For example, calling into a native export on
such an assembly 
&lt;li&gt;
Native activation of a native runtime-provided COM CLSID – Such as CoCreateInstance
on ICLRRuntimeHost’s CLSID 
&lt;li&gt;
Native activation of a managed framework CLSID – Such as CoCreateInstance on System.ArrayList’s
CLSID (extremely rare)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
All these have a “single runtime per process” view of the world, so we try to make
those codepaths believe they still exist in that world by “unifying” the version that
they see.&amp;nbsp; After a given version has been chosen by one of these codepaths, that’s
the version that all of them see for the remainder of the process lifetime.&amp;nbsp;
Additionally, all of these activation paths had some kind of roll-forward semantics
associated with them.&amp;nbsp; We “cap” those semantics at v2, meaning by default none
of these codepaths see v4 at all.&amp;nbsp; This allows us to claim that installing v4
is “non-impactful”.&amp;nbsp; It should not change the behavior of existing components
when installed. (Note that this has the interesting side-effect of a v4 only machine
appearing to have no runtimes installed at all via these codepaths.)
&lt;/p&gt;
&lt;p&gt;
This is all well and good until someone WANTS those codepaths to see v4.&amp;nbsp; Rolling
a v2 managed app forward to v4 using a config (without the attribute) works just fine,
unless that app also expects interaction with these “legacy” codepaths to be associated
with the current runtime (v4).&amp;nbsp; For instance, a p/Invoke to GetCorSystemDirectory
in order to construct a path to Fusion.dll (please don’t do that, BTW) will give you
v2’s fusion.dll.&amp;nbsp; COM activation of a managed COM object will prefer the runtime
it was built against rather than load into the current runtime (meaning you may be
dealing with interop rather than a concrete CLR type). That may work, and it may not,
depending on what you’re doing. 
&lt;p&gt;
The useLegacyV2RuntimeActivationPolicy attribute basically lets you say, “I have some
dependencies on the legacy shim APIs.&amp;nbsp; Please make them work the way they used
to with respect to the chosen runtime.”&amp;nbsp; In that context, hopefully the name
makes more sense to you. It is *&lt;b&gt;mostly&lt;/b&gt;* equivalent to calling CorBindToRuntimeEx
using the full version string for v4.&amp;nbsp; We also have a &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=ecc34c3c-be44-4422-86b7-900900e451f9&amp;amp;url=http%3a%2f%2fmsdn.microsoft.com%2fen-us%2flibrary%2fee426955(VS.100).aspx" target="_blank"&gt;method
in our new shim APIs&lt;/a&gt; to do this programmatically, the difference being that in
a config file, it can be done declaratively, which is useful for a host that uses
config files to determine which runtime to load plugins into. (the attributes value
(or lack of value) is conveyed back to a host via the pdwConfigFlags parameter of &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=ecc34c3c-be44-4422-86b7-900900e451f9&amp;amp;url=http%3a%2f%2fmsdn.microsoft.com%2fen-us%2flibrary%2fdd380612(VS.100).aspx" target="_blank"&gt;ICLRMetaHostPolicy::GetRequestedRuntime&lt;/a&gt;) 
&lt;p&gt;
One of the big reasons people need to do this is if they have a dependency on a pre-v4
IJW assembly.&amp;nbsp; By default, we can’t allow those to load into v4*.&amp;nbsp; Putting
this attribute in your config allows this to happen. 
&lt;p&gt;
Why don’t we make this the default behavior? You might argue that this behavior is
more compatible, and makes porting code from previous versions much easier. If you’ll
recall, this can’t be the default behavior because it would make installation of v4
impactful, which can break existing apps installed on your machine. 
&lt;p&gt;
Well, why don’t we make this the default behavior for v4 managed apps?&amp;nbsp; Well,
that is precisely the behavior we had for beta 1.&amp;nbsp; As we started trying to explain
the behavior to people, we found it was very difficult to explain how these legacy
codepaths worked.&amp;nbsp; We ultimately decided that making the behavior consistent
was better.&amp;nbsp; The example that ultimately convinced me we had made the right choice
was that the behavior of a library would change based on whether it was hosted by
a native process or a managed one.&amp;nbsp; That seemed really bad to me. 
&lt;p&gt;
You might say, “Why shouldn’t I just set this for every app I have?” Well, the downside
of this attribute is that it turns off in-proc SxS with pre-v4 runtimes.&amp;nbsp; It
locks them out of the process.&amp;nbsp; This may not matter to your scenario.&amp;nbsp; If
you look at some of the runtime tools, they are using this attribute.&amp;nbsp; Even Visual
Studio uses this attribute.&amp;nbsp; Don’t just blindly use it though.&amp;nbsp; If you'
find yourself needing it in something other than a migration aid, or for loading pre-v4
mixed-mode assemblies (which we hope becomes more rare moving forward as people start
updating the interesting mixed-mode binaries out there), I’d like to know about it.&amp;nbsp;
Leave me a comment! 
&lt;p&gt;
Hopefully, you’ve got a better handle on exactly what this attribute means, and can
make a more informed decision about when it is appropriate to use. 
&lt;p&gt;
&lt;em&gt;*There are many engineering challenges around in-proc SxS and IJW assemblies.&amp;nbsp;
Currently, pre-v4 IJW assemblies can only load into the runtime that is associated
with the “legacy shim APIs”.&amp;nbsp; But any given IJW assembly (regardless of version)
may only be loaded into a single runtime per process at this time.&lt;/em&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=ecc34c3c-be44-4422-86b7-900900e451f9" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,ecc34c3c-be44-4422-86b7-900900e451f9.aspx</comments>
      <category>CLR</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=65e9edd3-21c0-4f6d-bcc0-6e9f11144591</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,65e9edd3-21c0-4f6d-bcc0-6e9f11144591.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,65e9edd3-21c0-4f6d-bcc0-6e9f11144591.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=65e9edd3-21c0-4f6d-bcc0-6e9f11144591</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
My brother-in-law posted a note on Facebook that was basically one of those silly
things you do and perpetuate across the internet.  I usually don’t take part
in such things, but this one seemed interesting, and I’ve been thinking about ways
to jumpstart my blogging again now that the embargo on all the cool stuff is lifted. 
So, I thought I would do it.  Here are the rules:
</p>
        <ul>
          <li>
Grab the book nearest you. Right now.</li>
          <li>
Turn to page 56.</li>
          <li>
Find the fifth sentence.</li>
          <li>
Post that sentence along with these instructions in a note to your wall. <em>(this
was on Facebook, so it is referring to that wall)</em></li>
          <li>
Don't dig for your favorite book, the coolest, the most intellectual. Use the CLOSEST.</li>
        </ul>
        <p>
So, it took me a while to determine which book was the “closest”, as my position is
roughly normal to the bookshelf in my office.  I finally decided to be honest
and pick the one that was really closest, but I will share another that was very close,
as it is a good segue into future blogs.
</p>
        <p>
The first (and official) one:
</p>
        <blockquote>
          <p>
Semiconductor materials at 0 K have basically the same structure as insulators – a
filled valence band separated from an empty conduction band by a band gap containing
no allowed energy states (Fig. 3-4).
</p>
          <p align="right">
            <em>Solid State Electronic Devices, Ben G. Streetman</em>
          </p>
        </blockquote>
        <p>
The second, and more relevant/interesting one:
</p>
        <blockquote>
          <p>
The shim’s algorithm for picking a version in the COM interoperability scenario is
much more straightforward – the latest version installed on the machine is always
used.
</p>
          <p align="right">
            <em>Customizing the Microsoft .NET Framework Common Language Runtime, Steven Pratschner</em>
          </p>
        </blockquote>
        <p>
What is amazing about this second one is that this is directly related to one of the
features I’ve been working on for CLR v4 (and yes, that is actually the 5th sentence
on page 56).  Namely, this feature is known as “in-process side by side” (or
in-proc SxS for short), and was announced publicly at PDC last month.  This feature
allows you to have more than version of the CLR loaded and running in a single process.
</p>
        <p>
This feature is primarily a compatibility feature, targeted precisely at the behavior
noted in the quote above.  When we use the latest version, we can break existing
COM objects.  Not only because of breaking changes we make (of which the number
is fairly small), but because of other, more subtle behavior dependencies.
</p>
        <p>
Previously, loading a CLR version into the process locked the process to that CLR
version.  Any other policy than “pick the latest” results in a load order dependency
problem that can result in “for sure” breaks because COM components targeting newer
runtimes cannot run on old runtimes.  So, clearly, that was the best choice of
policies.
</p>
        <p>
Now that we support multiple runtimes in the process (v2 and above), we can make a
smarter, more compatible choice about runtime activation.  The precise policies
are still being worked through, so I’ll avoid stating them explicitly, but you can
imagine us being able to make a much better choice about what runtime to activate
to run a given managed COM component.
</p>
        <p>
I’ll be posting more about this feature and it’s implications soon.  Feel free
to seed my future posts with questions in the comments.  Hopefully, this is the
jumpstart I needed.  As for the “game” above, feel free to do it, or ignore it. 
It won’t result in any difference to your luck, financial situation, or anything else.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=65e9edd3-21c0-4f6d-bcc0-6e9f11144591" />
      </body>
      <title>Random fun book thing and CLR In-Proc SxS</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,65e9edd3-21c0-4f6d-bcc0-6e9f11144591.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,65e9edd3-21c0-4f6d-bcc0-6e9f11144591.aspx</link>
      <pubDate>Fri, 21 Nov 2008 01:25:12 GMT</pubDate>
      <description>&lt;p&gt;
My brother-in-law posted a note on Facebook that was basically one of those silly
things you do and perpetuate across the internet.&amp;nbsp; I usually don’t take part
in such things, but this one seemed interesting, and I’ve been thinking about ways
to jumpstart my blogging again now that the embargo on all the cool stuff is lifted.&amp;nbsp;
So, I thought I would do it.&amp;nbsp; Here are the rules:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Grab the book nearest you. Right now.&lt;/li&gt;
&lt;li&gt;
Turn to page 56.&lt;/li&gt;
&lt;li&gt;
Find the fifth sentence.&lt;/li&gt;
&lt;li&gt;
Post that sentence along with these instructions in a note to your wall. &lt;em&gt;(this
was on Facebook, so it is referring to that wall)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
Don't dig for your favorite book, the coolest, the most intellectual. Use the CLOSEST.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
So, it took me a while to determine which book was the “closest”, as my position is
roughly normal to the bookshelf in my office.&amp;nbsp; I finally decided to be honest
and pick the one that was really closest, but I will share another that was very close,
as it is a good segue into future blogs.
&lt;/p&gt;
&lt;p&gt;
The first (and official) one:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Semiconductor materials at 0 K have basically the same structure as insulators – a
filled valence band separated from an empty conduction band by a band gap containing
no allowed energy states (Fig. 3-4).
&lt;/p&gt;
&lt;p align="right"&gt;
&lt;em&gt;Solid State Electronic Devices, Ben G. Streetman&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
The second, and more relevant/interesting one:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
The shim’s algorithm for picking a version in the COM interoperability scenario is
much more straightforward – the latest version installed on the machine is always
used.
&lt;/p&gt;
&lt;p align="right"&gt;
&lt;em&gt;Customizing the Microsoft .NET Framework Common Language Runtime, Steven Pratschner&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
What is amazing about this second one is that this is directly related to one of the
features I’ve been working on for CLR v4 (and yes, that is actually the 5th sentence
on page 56).&amp;nbsp; Namely, this feature is known as “in-process side by side” (or
in-proc SxS for short), and was announced publicly at PDC last month.&amp;nbsp; This feature
allows you to have more than version of the CLR loaded and running in a single process.
&lt;/p&gt;
&lt;p&gt;
This feature is primarily a compatibility feature, targeted precisely at the behavior
noted in the quote above.&amp;nbsp; When we use the latest version, we can break existing
COM objects.&amp;nbsp; Not only because of breaking changes we make (of which the number
is fairly small), but because of other, more subtle behavior dependencies.
&lt;/p&gt;
&lt;p&gt;
Previously, loading a CLR version into the process locked the process to that CLR
version.&amp;nbsp; Any other policy than “pick the latest” results in a load order dependency
problem that can result in “for sure” breaks because COM components targeting newer
runtimes cannot run on old runtimes.&amp;nbsp; So, clearly, that was the best choice of
policies.
&lt;/p&gt;
&lt;p&gt;
Now that we support multiple runtimes in the process (v2 and above), we can make a
smarter, more compatible choice about runtime activation.&amp;nbsp; The precise policies
are still being worked through, so I’ll avoid stating them explicitly, but you can
imagine us being able to make a much better choice about what runtime to activate
to run a given managed COM component.
&lt;/p&gt;
&lt;p&gt;
I’ll be posting more about this feature and it’s implications soon.&amp;nbsp; Feel free
to seed my future posts with questions in the comments.&amp;nbsp; Hopefully, this is the
jumpstart I needed.&amp;nbsp; As for the “game” above, feel free to do it, or ignore it.&amp;nbsp;
It won’t result in any difference to your luck, financial situation, or anything else.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=65e9edd3-21c0-4f6d-bcc0-6e9f11144591" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,65e9edd3-21c0-4f6d-bcc0-6e9f11144591.aspx</comments>
      <category>CLR</category>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=498e2e35-1590-4852-92e1-2212157c68f1</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,498e2e35-1590-4852-92e1-2212157c68f1.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,498e2e35-1590-4852-92e1-2212157c68f1.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=498e2e35-1590-4852-92e1-2212157c68f1</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I've been doing some app-building with Silverlight lately and exploring the limitations
of the platform in comparison to the full desktop CLR and what that means for the
Silverlight "ecosystem".  Those limitations can be summed up with 3 items:
</p>
        <ol>
          <li>
Strict sandbox security model</li>
          <li>
Reduced managed framework surface area</li>
          <li>
No binary compatibility with libraries targeting the desktop CLR (eliminates the number
of 3rd party components you can leverage).</li>
        </ol>
        <p>
I think #3 will begin to become a non-issue as more component providers provide builds
for Silverlight. #2 can be broken down into 2 areas:
</p>
        <ul>
          <li>
Full technology areas that are unavailable on Silverlight (LinqToSql, WinForms, etc)</li>
          <li>
Reduced/pruned APIs</li>
        </ul>
        <p>
The second is where my interest lies, and intersects with #1 (the new security model). 
We've done extensive threat modeling against our APIs as well as automated tooling
that has either removed (or made internal) certain APIs, or marked them as SecurityCritical,
meaning they cannot be called directly from "user" code.
</p>
        <p>
In addition, the security model requires safe, verifiable user code.  Normally
when developing on the desktop CLR, unless you are specifically targeting a low trust
environment, you can do whatever you like.
</p>
        <p>
So, for this exercise, I pulled out my trusty STDF parser (blogged <a href="http://www.marklio.com/marklio/ct.ashx?id=498e2e35-1590-4852-92e1-2212157c68f1&amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2ce3601f31-231b-4a82-b5a7-1c31600ce25c.aspx" target="_blank">here</a> and <a href="http://www.marklio.com/marklio/ct.ashx?id=498e2e35-1590-4852-92e1-2212157c68f1&amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2c3a89ecce-89a8-470e-a894-bc5cc86ce41d.aspx" target="_blank">here</a>). 
I've used this project as a test vehicle for both v2.0 and Orcas, and it's served
well as a project that leverages a large cross-section of features in the Framework,
from high-level stuff like Linq down to expression tree inspection and further down
to LCG/RefEmit.
</p>
        <p>
In short, I was able to get the parser working without too much trouble. I felt like
creating a source bed that intended to target both Silverlight and the Desktop should
be an attainable goal.  You just have to switch your mindset from binary compatibility
to source compatibility.
</p>
        <p>
I combated the reduced surface area with extension methods, which worked quite well
to centralize the "overload shims" that needed to be "Silverlight-only", as well as
for a general refactoring tool.  My goal is to have all the desktop vs. Silverlight
differences centralized into files that are either included or excluded from the build
depending on which platform I'm targeting.  I wish you could create extension
properties.  That would let me close all the surface area discrepancies that
aren't caused by missing/irrelevant technology areas.
</p>
        <p>
I was pleased that 99% of my LCG codegen stuff "just worked".  I make heavy use
of Reflection.Emit via DynamicMethod to generate my record parsers based on attributes
on the record classes.  The 2 problems I ran into were:
</p>
        <ul>
          <li>
Visibility restrictions - The new security model won't let my dynamic methods see
internals.  I had used this ability to keep the API clean.  I'm still figuring
out the best approach, but it was simple enough just to expose those methods.</li>
          <li>
Verifiability - I had a few places where I was generating unverifiable code. 
Some of these were my own codegen bugs, but others were just bad assumptions on my
part.</li>
        </ul>
        <p>
This brings me to <a href="http://www.marklio.com/marklio/ct.ashx?id=498e2e35-1590-4852-92e1-2212157c68f1&amp;url=http%3a%2f%2fmsdn2.microsoft.com%2fen-us%2flibrary%2fsystem.reflection.emit.opcodes.constrained.aspx" target="_blank">constrained
callvirt</a>, an interesting little IL tidbit I discovered in the porting process. 
Calling conventions are subtly different between reference types and value types,
and it also depends on whether the given method is actually overridden in the value
type (which can lead to confusing breaks when that state changes).  In the v1.x
days, you always knew the type you were dealing with, so it didn't matter that much
and you could generally always create the right sequence of IL to make a call. 
V2.0 introduced generics, which meant that you couldn't emit unified IL for both the
possibility of reference types or value types.  This meant there needed to be
a way to unify the IL for the 2 cases.  This is where the constrained prefix
came in.  It allows you to write unified IL that works regardless of whether
you're working with a value type or a reference type (think generics constrained by
an interface, or calling a method defined on System.Object like ToString()).
</p>
        <p>
Anyway, I was able to fix my unverifiable code by utilizing the constrained prefix. 
It also simplified my codegen logic significantly in a number of places where I had
different paths based on whether I was working with a value type or not.
</p>
        <p>
All in all, I was pleased with the results.  I'll be posting a sample Silverlight
app using the library when I get some UI stuff figured out.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=498e2e35-1590-4852-92e1-2212157c68f1" />
      </body>
      <title>Silverlight limitations and Constrained Callvirt in IL</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,498e2e35-1590-4852-92e1-2212157c68f1.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,498e2e35-1590-4852-92e1-2212157c68f1.aspx</link>
      <pubDate>Wed, 23 Apr 2008 20:43:46 GMT</pubDate>
      <description>&lt;p&gt;
I've been doing some app-building with Silverlight lately and exploring the limitations
of the platform in comparison to the full desktop CLR and what that means for the
Silverlight "ecosystem".&amp;nbsp; Those limitations can be summed up with 3 items:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Strict sandbox security model&lt;/li&gt;
&lt;li&gt;
Reduced managed framework surface area&lt;/li&gt;
&lt;li&gt;
No binary compatibility with libraries targeting the desktop CLR (eliminates the number
of 3rd party components you can leverage).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
I think #3 will begin to become a non-issue as more component providers provide builds
for Silverlight. #2 can be broken down into 2 areas:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Full technology areas that are unavailable on Silverlight (LinqToSql, WinForms, etc)&lt;/li&gt;
&lt;li&gt;
Reduced/pruned APIs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
The second is where my interest lies, and intersects with #1 (the new security model).&amp;nbsp;
We've done extensive threat modeling against our APIs as well as automated tooling
that has either removed (or made internal) certain APIs, or marked them as SecurityCritical,
meaning they cannot be called directly from "user" code.
&lt;/p&gt;
&lt;p&gt;
In addition, the security model requires safe, verifiable user code.&amp;nbsp; Normally
when developing on the desktop CLR, unless you are specifically targeting a low trust
environment, you can do whatever you like.
&lt;/p&gt;
&lt;p&gt;
So, for this exercise, I pulled out my trusty STDF parser (blogged &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=498e2e35-1590-4852-92e1-2212157c68f1&amp;amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2ce3601f31-231b-4a82-b5a7-1c31600ce25c.aspx" target="_blank"&gt;here&lt;/a&gt; and &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=498e2e35-1590-4852-92e1-2212157c68f1&amp;amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2c3a89ecce-89a8-470e-a894-bc5cc86ce41d.aspx" target="_blank"&gt;here&lt;/a&gt;).&amp;nbsp;
I've used this project as a test vehicle for both v2.0 and Orcas, and it's served
well as a project that leverages a large cross-section of features in the Framework,
from high-level stuff like Linq down to expression tree inspection and further down
to LCG/RefEmit.
&lt;/p&gt;
&lt;p&gt;
In short, I was able to get the parser working without too much trouble. I felt like
creating a source bed that intended to target both Silverlight and the Desktop should
be an attainable goal.&amp;nbsp; You just have to switch your mindset from binary compatibility
to source compatibility.
&lt;/p&gt;
&lt;p&gt;
I combated the reduced surface area with extension methods, which worked quite well
to centralize the "overload shims" that needed to be "Silverlight-only", as well as
for a general refactoring tool.&amp;nbsp; My goal is to have all the desktop vs. Silverlight
differences centralized into files that are either included or excluded from the build
depending on which platform I'm targeting.&amp;nbsp; I wish you could create extension
properties.&amp;nbsp; That would let me close all the surface area discrepancies that
aren't caused by missing/irrelevant technology areas.
&lt;/p&gt;
&lt;p&gt;
I was pleased that 99% of my LCG codegen stuff "just worked".&amp;nbsp; I make heavy use
of Reflection.Emit via DynamicMethod to generate my record parsers based on attributes
on the record classes.&amp;nbsp; The 2 problems I ran into were:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Visibility restrictions - The new security model won't let my dynamic methods see
internals.&amp;nbsp; I had used this ability to keep the API clean.&amp;nbsp; I'm still figuring
out the best approach, but it was simple enough just to expose those methods.&lt;/li&gt;
&lt;li&gt;
Verifiability - I had a few places where I was generating unverifiable code.&amp;nbsp;
Some of these were my own codegen bugs, but others were just bad assumptions on my
part.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
This brings me to &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=498e2e35-1590-4852-92e1-2212157c68f1&amp;amp;url=http%3a%2f%2fmsdn2.microsoft.com%2fen-us%2flibrary%2fsystem.reflection.emit.opcodes.constrained.aspx" target="_blank"&gt;constrained
callvirt&lt;/a&gt;, an interesting little IL tidbit I discovered in the porting process.&amp;nbsp;
Calling conventions are subtly different between reference types and value types,
and it also depends on whether the given method is actually overridden in the value
type (which can lead to confusing breaks when that state changes).&amp;nbsp; In the v1.x
days, you always knew the type you were dealing with, so it didn't matter that much
and you could generally always create the right sequence of IL to make a call.&amp;nbsp;
V2.0 introduced generics, which meant that you couldn't emit unified IL for both the
possibility of reference types or value types.&amp;nbsp; This meant there needed to be
a way to unify the IL for the 2 cases.&amp;nbsp; This is where the constrained prefix
came in.&amp;nbsp; It allows you to write unified IL that works regardless of whether
you're working with a value type or a reference type (think generics constrained by
an interface, or calling a method defined on System.Object like ToString()).
&lt;/p&gt;
&lt;p&gt;
Anyway, I was able to fix my unverifiable code by utilizing the constrained prefix.&amp;nbsp;
It also simplified my codegen logic significantly in a number of places where I had
different paths based on whether I was working with a value type or not.
&lt;/p&gt;
&lt;p&gt;
All in all, I was pleased with the results.&amp;nbsp; I'll be posting a sample Silverlight
app using the library when I get some UI stuff figured out.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=498e2e35-1590-4852-92e1-2212157c68f1" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,498e2e35-1590-4852-92e1-2212157c68f1.aspx</comments>
      <category>CLR</category>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=1fa8a82b-a6d6-4fbb-8cca-5e352ff3c9e9</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,1fa8a82b-a6d6-4fbb-8cca-5e352ff3c9e9.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,1fa8a82b-a6d6-4fbb-8cca-5e352ff3c9e9.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=1fa8a82b-a6d6-4fbb-8cca-5e352ff3c9e9</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>This is one of those entries that attempts to fill a void in online search for
a particular topic.  I ramble on for a while to give enough context so that a
search engine can match it up in a relevant manner.</em>
        </p>
        <p>
I was debugging something the other day, and thought I had come across a heinous bug
in the CLR.  Turns out, everything was working fine and the bug was in the app.
</p>
        <p>
A program was crashing and it was a managed exception, so I attached to it with VS2008
and dug in.  The first thing I noted was that this was a retail build, so <a href="http://www.marklio.com/marklio/ct.ashx?id=1fa8a82b-a6d6-4fbb-8cca-5e352ff3c9e9&amp;url=http%3a%2f%2fwww.hanselman.com%2fblog%2fReleaseISNOTDebug64bitOptimizationsAndCMethodInliningInReleaseBuildCallStacks.aspx" target="_blank">my
stack was collapsed in a number of places</a>... expected, keep moving.  Then,
I noted an interesting frame on my stack (this is a contrived example, not the actual
thing I saw):
</p>
        <blockquote>
          <p>
&gt;    CanonTest.exe!CanonTest.GenericType&lt;<font color="#ff0000"><strong>System.__Canon</strong></font>,int&gt;.SomeOperation()
+ 0x55 bytes    
</p>
        </blockquote>
        <p>
That's weird, what is System.__Canon and what's it doing here? Surely this must be
a horrible CLR bug where my method tables are being corrupted!  Internet searches
seem to be confirming my thoughts.  A few others with random __Canon's showing
up on the stack do look like bugs.  After a bit more reasoning, I come to the
conclusion that System.__Canon must be special in some way since it follows the pattern
for such things...  marked internal, pre-pended with double-underscore.
</p>
        <p>
A few emails later, I had my answer.  System.__Canon is the special type that
is used to identify "canonical" generic type instantiations. It typically only shows
up in release builds, so you don't normally see it on the stack while debugging. 
So, it's easy to assume something's wrong when you do see it.
</p>
        <p>
If you'll recall, one of the really cool things about the Generics implementation
is that it allows for code sharing.  Jitted methods can be shared between compatible
type instantiations.  For instance, the code for SomeGenericType&lt;string&gt;
can likely be shared with SomeGenericType&lt;Foo&gt; (where Foo is another reference
type. We don't currently share code between value types, so you'll continue to see
those on the stack such as in the example).  That shared code needs to live somewhere,
so we have the concept of a "canonical" generic type instantiation that is identified
by __Canon as the type parameter.
</p>
        <p>
Also, in alot of debugger stack representations you'll get the GenericType`2 form
rather than expanded form.  In that case, you never see __Canon.
</p>
        <p>
For some more info on Generics and code sharing, see <a href="http://www.marklio.com/marklio/ct.ashx?id=1fa8a82b-a6d6-4fbb-8cca-5e352ff3c9e9&amp;url=http%3a%2f%2fblogs.msdn.com%2fjoelpob%2farchive%2f2004%2f11%2f17%2f259224.aspx" target="_blank">Joel
Pobar's excellent blog entry on the subject</a>.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=1fa8a82b-a6d6-4fbb-8cca-5e352ff3c9e9" />
      </body>
      <title>What is System.__Canon and why is it on my stack?</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,1fa8a82b-a6d6-4fbb-8cca-5e352ff3c9e9.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,1fa8a82b-a6d6-4fbb-8cca-5e352ff3c9e9.aspx</link>
      <pubDate>Tue, 12 Feb 2008 19:56:35 GMT</pubDate>
      <description>&lt;p&gt;
&lt;em&gt;This is one of those entries that attempts to fill a void in online search for
a particular topic.&amp;nbsp; I ramble on for a while to give enough context so that a
search engine can match it up in a relevant manner.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
I was debugging something the other day, and thought I had come across a heinous bug
in the CLR.&amp;nbsp; Turns out, everything was working fine and the bug was in the app.
&lt;/p&gt;
&lt;p&gt;
A program was crashing and it was a managed exception, so I attached to it with VS2008
and dug in.&amp;nbsp; The first thing I noted was that this was a retail build, so &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=1fa8a82b-a6d6-4fbb-8cca-5e352ff3c9e9&amp;amp;url=http%3a%2f%2fwww.hanselman.com%2fblog%2fReleaseISNOTDebug64bitOptimizationsAndCMethodInliningInReleaseBuildCallStacks.aspx" target="_blank"&gt;my
stack was collapsed in a number of places&lt;/a&gt;... expected, keep moving.&amp;nbsp; Then,
I noted an interesting frame on my stack (this is a contrived example, not the actual
thing I saw):
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CanonTest.exe!CanonTest.GenericType&amp;lt;&lt;font color="#ff0000"&gt;&lt;strong&gt;System.__Canon&lt;/strong&gt;&lt;/font&gt;,int&amp;gt;.SomeOperation()
+ 0x55 bytes&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
That's weird, what is System.__Canon and what's it doing here? Surely this must be
a horrible CLR bug where my method tables are being corrupted!&amp;nbsp; Internet searches
seem to be confirming my thoughts.&amp;nbsp; A few others with random __Canon's showing
up on the stack do look like bugs.&amp;nbsp; After a bit more reasoning, I come to the
conclusion that System.__Canon must be special in some way since it follows the pattern
for such things...&amp;nbsp; marked internal, pre-pended with double-underscore.
&lt;/p&gt;
&lt;p&gt;
A few emails later, I had my answer.&amp;nbsp; System.__Canon is the special type that
is used to identify "canonical" generic type instantiations. It typically only shows
up in release builds, so you don't normally see it on the stack while debugging.&amp;nbsp;
So, it's easy to assume something's wrong when you do see it.
&lt;/p&gt;
&lt;p&gt;
If you'll recall, one of the really cool things about the Generics implementation
is that it allows for code sharing.&amp;nbsp; Jitted methods can be shared between compatible
type instantiations.&amp;nbsp; For instance, the code for SomeGenericType&amp;lt;string&amp;gt;
can likely be shared with SomeGenericType&amp;lt;Foo&amp;gt; (where Foo is another reference
type. We don't currently share code between value types, so you'll continue to see
those on the stack such as in the example).&amp;nbsp; That shared code needs to live somewhere,
so we have the concept of a "canonical" generic type instantiation that is identified
by __Canon as the type parameter.
&lt;/p&gt;
&lt;p&gt;
Also, in alot of debugger stack representations you'll get the GenericType`2 form
rather than expanded form.&amp;nbsp; In that case, you never see __Canon.
&lt;/p&gt;
&lt;p&gt;
For some more info on Generics and code sharing, see &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=1fa8a82b-a6d6-4fbb-8cca-5e352ff3c9e9&amp;amp;url=http%3a%2f%2fblogs.msdn.com%2fjoelpob%2farchive%2f2004%2f11%2f17%2f259224.aspx" target="_blank"&gt;Joel
Pobar's excellent blog entry on the subject&lt;/a&gt;.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=1fa8a82b-a6d6-4fbb-8cca-5e352ff3c9e9" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,1fa8a82b-a6d6-4fbb-8cca-5e352ff3c9e9.aspx</comments>
      <category>CLR</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=df8d6471-83fd-4f66-a799-ef8274979f0e</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,df8d6471-83fd-4f66-a799-ef8274979f0e.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,df8d6471-83fd-4f66-a799-ef8274979f0e.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=df8d6471-83fd-4f66-a799-ef8274979f0e</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
The CTP for the MVC framework includes support for master-page, page, and user-control
based views.  I thought it might be interesting to enable .ashx-based views for
things like RSS generation via System.Xml.Linq, or other more "raw" view output.
</p>
        <p>
As it turns out, this is fairly trivial.  The place we need to extend is the
IViewFactory returned by Controller.ViewFactory.  This is the component that
is responsible for creating the view when a call to RenderView is made.
</p>
        <p>
The default view factory is the WebFormViewFactory, which knows how to generate views
based on .master, .aspx, and .ascx views.  Since we want to add support for .ashx,
we'll use WebFormViewFactory as a starting place.  We'll inherit from WebFormViewFactory
and override CreateView to supply our extra .ashx lookup.
</p>
        <pre>
          <span style="color: #0000ff">using</span> System; <span style="color: #0000ff">using</span> System.Globalization; <span style="color: #0000ff">using</span> System.IO; <span style="color: #0000ff">using</span> System.Web; <span style="color: #0000ff">using</span> System.Web.Compilation; <span style="color: #0000ff">using</span> System.Web.Mvc; <span style="color: #0000ff">public</span><span style="color: #0000ff">class</span> SpecialViewFactory
: WebFormViewFactory { <span style="color: #0000ff">static</span><span style="color: #0000ff">readonly</span><span style="color: #0000ff">string</span>[]
ViewLocationFormats = <span style="color: #0000ff">new</span><span style="color: #0000ff">string</span>[]
{ "<span style="color: #8b0000">~/Views/{1}/{0}.ashx</span>", "<span style="color: #8b0000">~/Views/Shared/{0}.ashx</span>"
}; ControllerContext _ControllerContext; #region IViewFactory Members <span style="color: #0000ff">protected</span><span style="color: #0000ff">override</span> IView
CreateView(ControllerContext controllerContext, <span style="color: #0000ff">string</span> viewName, <span style="color: #0000ff">string</span> masterName, <span style="color: #0000ff">object</span> viewData)
{ _ControllerContext = controllerContext; <span style="color: #008000">//check to
see if there is an ashx that matches here.</span><span style="color: #0000ff">object</span><span style="color: #0000ff">value</span> = <span style="color: #0000ff">null</span>;
controllerContext.RouteData.Values.TryGetValue("<span style="color: #8b0000">controller</span>", <span style="color: #0000ff">out</span><span style="color: #0000ff">value</span>); <span style="color: #0000ff">string</span> controllerName
= <span style="color: #0000ff">value</span><span style="color: #0000ff">as</span><span style="color: #0000ff">string</span>; <span style="color: #0000ff">if</span> (controllerName
== <span style="color: #0000ff">null</span>) { <span style="color: #0000ff">throw</span><span style="color: #0000ff">new</span> InvalidOperationException("<span style="color: #8b0000">No
route data value available for controller.</span>"); } Type viewType = <span style="color: #0000ff">null</span>; <span style="color: #0000ff">foreach</span> (var
loc <span style="color: #0000ff">in</span> ViewLocationFormats) { var path = <span style="color: #0000ff">string</span>.Format(CultureInfo.InvariantCulture,
loc, viewName, controllerName); viewType = GetCompiledType(path); <span style="color: #0000ff">if</span> (viewType
!= <span style="color: #0000ff">null</span>) <span style="color: #0000ff">break</span>;
} <span style="color: #0000ff">if</span> (viewType == <span style="color: #0000ff">null</span>)
{ <span style="color: #0000ff">return</span><span style="color: #0000ff">base</span>.CreateView(controllerContext,
viewName, masterName, viewData); } <span style="color: #0000ff">if</span> (!<span style="color: #0000ff">typeof</span>(IView).IsAssignableFrom(viewType))
{ <span style="color: #008000">//TODO: better exception</span><span style="color: #0000ff">throw</span><span style="color: #0000ff">new</span> InvalidOperationException("<span style="color: #8b0000">Type
not a view</span>"); } var view = (IView)Activator.CreateInstance(viewType); var viewHandler
= view <span style="color: #0000ff">as</span> ViewHandler; <span style="color: #0000ff">if</span> (viewHandler
!= <span style="color: #0000ff">null</span>) viewHandler.ViewData = viewData; _ControllerContext
= <span style="color: #0000ff">null</span>; <span style="color: #0000ff">return</span> view;
} <span style="color: #0000ff">private</span> Type GetCompiledType(<span style="color: #0000ff">string</span> path)
{ Type compiledType = <span style="color: #0000ff">null</span>; <span style="color: #0000ff">try</span> { <span style="color: #0000ff">if</span> (File.Exists(_ControllerContext.HttpContext.Request.MapPath(path)))
{ compiledType = BuildManager.GetCompiledType(path); } } <span style="color: #0000ff">catch</span> (HttpCompileException)
{ <span style="color: #0000ff">throw</span>; } <span style="color: #0000ff">catch</span> (HttpParseException)
{ <span style="color: #0000ff">throw</span>; } <span style="color: #0000ff">catch</span> (HttpException)
{ } <span style="color: #0000ff">return</span> compiledType; } #endregion } </pre>
        <p>
GetCompiledType had to be replicated as it isn't exposed in the base class. 
Note, I added a File.Exists check before I attempt to get the compiled type from the
BuildManager. This was really to avoid having to deal with a bunch of first chance
exceptions in the debug, although it seems likely that avoiding the exception is a
good thing.  It wouldn't catch handlers that are mapped in the app dynamically
or via web.config.
</p>
        <p>
As you can see, I also added a ViewHandler class that my handlers can inherit from
that gives them the same goodies that the other views get, but I'll leave that as
an exercise for the reader to implement.
</p>
        <p>
So, now the only thing remaining is to inject our special view factory into the pipeline
instead of the default.  A simple way to do this is to set the ViewFactory property
in the constructor of any controller that needs .ashx support. Now, you can create
.ashx files and use them as views!
</p>
        <p>
Next time, I'll show you how to add support for routing controller actions based on
data not in the URL.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=df8d6471-83fd-4f66-a799-ef8274979f0e" />
      </body>
      <title>Adding support for .ashx-based views in ASP.net MVC</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,df8d6471-83fd-4f66-a799-ef8274979f0e.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,df8d6471-83fd-4f66-a799-ef8274979f0e.aspx</link>
      <pubDate>Thu, 03 Jan 2008 23:46:58 GMT</pubDate>
      <description>&lt;p&gt;
The CTP for the MVC framework includes support for master-page, page, and user-control
based views.&amp;nbsp; I thought it might be interesting to enable .ashx-based views for
things like RSS generation via System.Xml.Linq, or other more "raw" view output.
&lt;/p&gt;
&lt;p&gt;
As it turns out, this is fairly trivial.&amp;nbsp; The place we need to extend is the
IViewFactory returned by Controller.ViewFactory.&amp;nbsp; This is the component that
is responsible for creating the view when a call to RenderView is made.
&lt;/p&gt;
&lt;p&gt;
The default view factory is the WebFormViewFactory, which knows how to generate views
based on .master, .aspx, and .ascx views.&amp;nbsp; Since we want to add support for .ashx,
we'll use WebFormViewFactory as a starting place.&amp;nbsp; We'll inherit from WebFormViewFactory
and override CreateView to supply our extra .ashx lookup.
&lt;/p&gt;
&lt;pre&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Globalization; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.IO; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Web; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Web.Compilation; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Web.Mvc; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; SpecialViewFactory
: WebFormViewFactory { &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;[]
ViewLocationFormats = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;[]
{ "&lt;span style="color: #8b0000"&gt;~/Views/{1}/{0}.ashx&lt;/span&gt;", "&lt;span style="color: #8b0000"&gt;~/Views/Shared/{0}.ashx&lt;/span&gt;"
}; ControllerContext _ControllerContext; #region IViewFactory Members &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; IView
CreateView(ControllerContext controllerContext, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; viewName, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; masterName, &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; viewData)
{ _ControllerContext = controllerContext; &lt;span style="color: #008000"&gt;//check to
see if there is an ashx that matches here.&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; &lt;span style="color: #0000ff"&gt;value&lt;/span&gt; = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;
controllerContext.RouteData.Values.TryGetValue("&lt;span style="color: #8b0000"&gt;controller&lt;/span&gt;", &lt;span style="color: #0000ff"&gt;out&lt;/span&gt; &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;); &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; controllerName
= &lt;span style="color: #0000ff"&gt;value&lt;/span&gt; &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (controllerName
== &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) { &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; InvalidOperationException("&lt;span style="color: #8b0000"&gt;No
route data value available for controller.&lt;/span&gt;"); } Type viewType = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;; &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var
loc &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; ViewLocationFormats) { var path = &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(CultureInfo.InvariantCulture,
loc, viewName, controllerName); viewType = GetCompiledType(path); &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (viewType
!= &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;
} &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (viewType == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
{ &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.CreateView(controllerContext,
viewName, masterName, viewData); } &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(IView).IsAssignableFrom(viewType))
{ &lt;span style="color: #008000"&gt;//TODO: better exception&lt;/span&gt; &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; InvalidOperationException("&lt;span style="color: #8b0000"&gt;Type
not a view&lt;/span&gt;"); } var view = (IView)Activator.CreateInstance(viewType); var viewHandler
= view &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; ViewHandler; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (viewHandler
!= &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) viewHandler.ViewData = viewData; _ControllerContext
= &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;; &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; view;
} &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; Type GetCompiledType(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; path)
{ Type compiledType = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;; &lt;span style="color: #0000ff"&gt;try&lt;/span&gt; { &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (File.Exists(_ControllerContext.HttpContext.Request.MapPath(path)))
{ compiledType = BuildManager.GetCompiledType(path); } } &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (HttpCompileException)
{ &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt;; } &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (HttpParseException)
{ &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt;; } &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (HttpException)
{ } &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; compiledType; } #endregion } &lt;/pre&gt;
&lt;p&gt;
GetCompiledType had to be replicated as it isn't exposed in the base class.&amp;nbsp;
Note, I added a File.Exists check before I attempt to get the compiled type from the
BuildManager. This was really to avoid having to deal with a bunch of first chance
exceptions in the debug, although it seems likely that avoiding the exception is a
good thing.&amp;nbsp; It wouldn't catch handlers that are mapped in the app dynamically
or via web.config.
&lt;/p&gt;
&lt;p&gt;
As you can see, I also added a ViewHandler class that my handlers can inherit from
that gives them the same goodies that the other views get, but I'll leave that as
an exercise for the reader to implement.
&lt;/p&gt;
&lt;p&gt;
So, now the only thing remaining is to inject our special view factory into the pipeline
instead of the default.&amp;nbsp; A simple way to do this is to set the ViewFactory property
in the constructor of any controller that needs .ashx support. Now, you can create
.ashx files and use them as views!
&lt;/p&gt;
&lt;p&gt;
Next time, I'll show you how to add support for routing controller actions based on
data not in the URL.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=df8d6471-83fd-4f66-a799-ef8274979f0e" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,df8d6471-83fd-4f66-a799-ef8274979f0e.aspx</comments>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=15185490-9b48-4e78-abd3-197862bf2554</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,15185490-9b48-4e78-abd3-197862bf2554.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,15185490-9b48-4e78-abd3-197862bf2554.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=15185490-9b48-4e78-abd3-197862bf2554</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>I wish I had time to come up with more concrete information (examples/code) in
this post, but I don't have the time to work that stuff up.  I did think it would
be useful for people searching for solutions to this problem, so here it is in all
its ambiguity.</em>
        </p>
        <p>
I was playing with expression tree inspection and dynamic interpretation the other
day, when I hit something that I was sure was a bug.  I was inspecting an expression
tree, identifying "branches" of interest, and generating lamdba expressions from them
on the fly.
</p>
        <p>
You might do this to break up an expression into separate units of execution to spread
across multiple processors (a la PLINQ), or to replace parts of a tree requiring local
execution before passing off to another layer to be transformed into another domain
like SQL, or whatever.  In any case, I was doing it.
</p>
        <p>
I found that if the type of the expression was a value type, I could not create a
lambda expression returning object from it, even though there is an inheritance relationship. 
You get a fairly straightforward, but perhaps surprising exception.
</p>
        <p>
After some back and forth with the Linq team, I discovered that this was by design. 
In the case of value types, the boxing operation required to make an object must be
represented by a unary convert expression. <strong>The solution is to wrap such expression
trees with a call to Expression.Convert(expression, typeof(object)).</strong></p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=15185490-9b48-4e78-abd3-197862bf2554" />
      </body>
      <title>Expression Tree Pruning, Value Types, and the one true Object</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,15185490-9b48-4e78-abd3-197862bf2554.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,15185490-9b48-4e78-abd3-197862bf2554.aspx</link>
      <pubDate>Thu, 30 Aug 2007 00:17:11 GMT</pubDate>
      <description>&lt;p&gt;
&lt;em&gt;I wish I had time to come up with more concrete information (examples/code) in
this post, but I don't have the time to work that stuff up.&amp;nbsp; I did think it would
be useful for people searching for solutions to this problem, so here it is in all
its ambiguity.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
I was playing with expression tree inspection and dynamic interpretation the other
day, when I hit something that I was sure was a bug.&amp;nbsp; I was inspecting an expression
tree, identifying "branches" of interest, and generating lamdba expressions from them
on the fly.
&lt;/p&gt;
&lt;p&gt;
You might do this to break up an expression into separate units of execution to spread
across multiple processors (a la PLINQ), or to replace parts of a tree requiring local
execution before passing off to another layer to be transformed into another domain
like SQL, or whatever.&amp;nbsp; In any case, I was doing it.
&lt;/p&gt;
&lt;p&gt;
I found that if the type of the expression was a value type, I could not create a
lambda expression returning object from it, even though there is an inheritance relationship.&amp;nbsp;
You get a fairly straightforward, but perhaps surprising exception.
&lt;/p&gt;
&lt;p&gt;
After some back and forth with the Linq team, I discovered that this was by design.&amp;nbsp;
In the case of value types, the boxing operation required to make an object must be
represented by a unary convert expression. &lt;strong&gt;The solution is to wrap such expression
trees with a call to Expression.Convert(expression, typeof(object)).&lt;/strong&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=15185490-9b48-4e78-abd3-197862bf2554" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,15185490-9b48-4e78-abd3-197862bf2554.aspx</comments>
      <category>CLR</category>
      <category>Fun</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=b12bddf4-a3a8-47d9-8e03-82e54a8f7c4c</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,b12bddf4-a3a8-47d9-8e03-82e54a8f7c4c.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,b12bddf4-a3a8-47d9-8e03-82e54a8f7c4c.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=b12bddf4-a3a8-47d9-8e03-82e54a8f7c4c</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
An interesting pattern I've seen emerge since the early releases of Orcas is what
I might refer to as "delegate properties".  What I mean by that is a property
(or field, I suppose) that returns a delegate.  This pattern has some interesting
implications.
</p>
        <p>
First, in a language that treats delegates as directly callable objects, this pattern
looks just like a method (<font face="Courier New">someInstance.TheProperty(args)</font>). 
You can't tell the difference (although VS gives you different intellisense) by looking
at a callsite like this. Among other things, this leads to some interesting naming
issues.  Do you name it like you would a method?
</p>
        <p>
Second, it opens up opportunities to do some really powerful (and slightly insane) hybrid
inheritance models.  Think about a virtual delegate property that has both a
getter and a setter, now think about trying to predict what that delegate will
do when you call it.  It doesn't sound like something to recommend as part of
a public API, but I think there are some interesting scenarios there.
</p>
        <p>
If I come up with something interesting and useful, I'll let you know.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=b12bddf4-a3a8-47d9-8e03-82e54a8f7c4c" />
      </body>
      <title>Delegate Properties</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,b12bddf4-a3a8-47d9-8e03-82e54a8f7c4c.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,b12bddf4-a3a8-47d9-8e03-82e54a8f7c4c.aspx</link>
      <pubDate>Thu, 26 Jul 2007 20:56:27 GMT</pubDate>
      <description>&lt;p&gt;
An interesting pattern I've seen emerge since the early releases of Orcas is what
I might refer to as "delegate properties".&amp;nbsp; What I mean by that is a property
(or field, I suppose)&amp;nbsp;that returns a delegate.&amp;nbsp; This pattern has some interesting
implications.
&lt;/p&gt;
&lt;p&gt;
First, in a language that treats delegates as directly callable objects, this pattern
looks just like a method (&lt;font face="Courier New"&gt;someInstance.TheProperty(args)&lt;/font&gt;).&amp;nbsp;
You can't tell the difference (although VS gives you different intellisense) by looking
at a callsite like this.&amp;nbsp;Among other things, this leads to some interesting naming
issues.&amp;nbsp; Do you name it like you would a method?
&lt;/p&gt;
&lt;p&gt;
Second, it opens up opportunities to do some really powerful (and slightly insane)&amp;nbsp;hybrid
inheritance models.&amp;nbsp; Think about a virtual delegate property that has both a
getter and a setter,&amp;nbsp;now think about trying to predict what that delegate will
do when you call it.&amp;nbsp; It doesn't sound like something to recommend as part of
a public API, but I think there are some interesting scenarios there.
&lt;/p&gt;
&lt;p&gt;
If I come up with something interesting and useful, I'll let you know.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=b12bddf4-a3a8-47d9-8e03-82e54a8f7c4c" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,b12bddf4-a3a8-47d9-8e03-82e54a8f7c4c.aspx</comments>
      <category>CLR</category>
      <category>Delegates</category>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=25ff5a1e-4369-4872-a992-bd271700d862</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,25ff5a1e-4369-4872-a992-bd271700d862.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,25ff5a1e-4369-4872-a992-bd271700d862.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=25ff5a1e-4369-4872-a992-bd271700d862</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
If you have been following my series on delegates, you may have experimented with
open-instance delegates and perhaps found it difficult to create an open-instance
delegate for a value type.
</p>
        <p>
If you'll recall, an open-instance delegate has an extra first parameter, used to
pass the instance used for the invocation.  What's not made explicitly clear
is that this first parameter must be passed by reference.
</p>
        <p>
For reference types, you've automatically got a reference, but for value types, this
must be a "ref" parameter.  For instance, a delegate type used as an open-instance
delegate for Int32.CompareTo would have to be defined something like:
</p>
        <blockquote>
          <p>
            <font face="Courier New">delegate int IntCompareToDelegate(<font color="#0000ff">ref</font> int
instance, int other);</font>
          </p>
        </blockquote>
        <p>
Otherwise, you'll get a System.ArgumentException when you try to bind the method to
the delegate, giving you the ever-helpful error message: "Error binding to target
method".
</p>
        <p>
There are lots of underlying reasons for this, both from a calling convention perspective,
as well as a side-effect perspective.  But, you can simplify it by thinking about
modifications to the instance.  If you passed by value (creating a copy that
the method acted on), any changes made to the instance by the method would be lost
because they happened to a copy.
</p>
        <p>
In most cases, value types are immutable in the framework, but you could run into
issues with your own types.  And, again, this isn't the only reason for this
restriction (take a look at the IL generated for a value-type method call to get some
more ideas).  It's just the easiest to understand.
</p>
        <p>
If you'll recall, Orcas extension methods, which are similar in concept to this, <a href="http://www.marklio.com/marklio/ct.ashx?id=25ff5a1e-4369-4872-a992-bd271700d862&amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2cf246bcec-5a5c-4869-b9c1-671d8f0daa4c.aspx" target="_blank">do
not follow this pattern</a> and are subject to the infamous value type copying problems.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=25ff5a1e-4369-4872-a992-bd271700d862" />
      </body>
      <title>Open-instance delegates for value types?</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,25ff5a1e-4369-4872-a992-bd271700d862.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,25ff5a1e-4369-4872-a992-bd271700d862.aspx</link>
      <pubDate>Mon, 16 Jul 2007 19:24:58 GMT</pubDate>
      <description>&lt;p&gt;
If you have been following my series on delegates, you may have experimented with
open-instance delegates and perhaps found it difficult to create an open-instance
delegate for a value type.
&lt;/p&gt;
&lt;p&gt;
If you'll recall, an open-instance delegate has an extra first parameter, used to
pass the instance used for the invocation.&amp;nbsp; What's not made explicitly clear
is that this first parameter must be passed by reference.
&lt;/p&gt;
&lt;p&gt;
For reference types, you've automatically got a reference, but for value types, this
must be a "ref" parameter.&amp;nbsp; For instance, a delegate type used as an open-instance
delegate for Int32.CompareTo would have to be defined something like:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;delegate int IntCompareToDelegate(&lt;font color=#0000ff&gt;ref&lt;/font&gt; int
instance, int other);&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Otherwise, you'll get a System.ArgumentException when you try to bind the method to
the delegate, giving you the ever-helpful error message: "Error binding to target
method".
&lt;/p&gt;
&lt;p&gt;
There are lots of underlying reasons for this, both from a calling convention perspective,
as well as a side-effect perspective.&amp;nbsp; But, you can simplify it by thinking about
modifications to the instance.&amp;nbsp; If you passed by value (creating a copy that
the method acted on), any changes made to the instance by the method would be lost
because they happened to a copy.
&lt;/p&gt;
&lt;p&gt;
In most cases, value types are immutable in the framework, but you could run into
issues with your own types.&amp;nbsp; And, again, this isn't the only reason for this
restriction (take a look at the IL generated for a value-type method call to get some
more ideas).&amp;nbsp; It's just the easiest to understand.
&lt;/p&gt;
&lt;p&gt;
If you'll recall, Orcas extension methods, which are similar in concept to this,&amp;nbsp;&lt;a href="http://www.marklio.com/marklio/ct.ashx?id=25ff5a1e-4369-4872-a992-bd271700d862&amp;amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2cf246bcec-5a5c-4869-b9c1-671d8f0daa4c.aspx" target=_blank&gt;do
not follow this pattern&lt;/a&gt; and are subject to the infamous value type copying problems.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=25ff5a1e-4369-4872-a992-bd271700d862" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,25ff5a1e-4369-4872-a992-bd271700d862.aspx</comments>
      <category>CLR</category>
      <category>Fun</category>
      <category>Technical</category>
      <category>Delegates</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=6e5f5bbf-bad3-44b8-a4ae-208c2f39be6d</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,6e5f5bbf-bad3-44b8-a4ae-208c2f39be6d.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,6e5f5bbf-bad3-44b8-a4ae-208c2f39be6d.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=6e5f5bbf-bad3-44b8-a4ae-208c2f39be6d</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I was helping a friend with a problem recently.  He was taking a set of serial
web service calls and doing them in parallel to save time, and was not up-to-speed
on the best approach for that.  Once he settled on an approach, he
realized that since his web service calls were being wrapped in an abstraction layer,
he didn't have the Begin/End asynchronous call methods that are provided by the proxy
class.
</p>
        <p>
"No problem, just wrap them in a delegate".  The compiler automatically gives
you Begin/EndInvoke methods in addition to the synchronous Invoke method.  And,
you're guaranteed not to mess up the implementation because it's all provided by the
CLR!  Just one of those things you might forget if you find yourself in the same
situation.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=6e5f5bbf-bad3-44b8-a4ae-208c2f39be6d" />
      </body>
      <title>Using delegates to get asynchronous invocation for free</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,6e5f5bbf-bad3-44b8-a4ae-208c2f39be6d.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,6e5f5bbf-bad3-44b8-a4ae-208c2f39be6d.aspx</link>
      <pubDate>Wed, 13 Jun 2007 23:37:55 GMT</pubDate>
      <description>&lt;p&gt;
I was helping a friend with a problem recently.&amp;nbsp; He was taking a set of serial
web service calls and doing them in parallel to save time, and was not up-to-speed
on the best approach for that.&amp;nbsp;&amp;nbsp;Once he&amp;nbsp;settled on an approach, he
realized that since his web service calls were being wrapped in an abstraction layer,
he didn't have the Begin/End asynchronous call methods that are provided by the proxy
class.
&lt;/p&gt;
&lt;p&gt;
"No problem, just wrap them in a delegate".&amp;nbsp; The compiler automatically gives
you Begin/EndInvoke methods in addition to the synchronous Invoke method.&amp;nbsp; And,
you're guaranteed not to mess up the implementation because it's all provided by the
CLR!&amp;nbsp; Just one of those things you might forget if you find yourself in the same
situation.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=6e5f5bbf-bad3-44b8-a4ae-208c2f39be6d" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,6e5f5bbf-bad3-44b8-a4ae-208c2f39be6d.aspx</comments>
      <category>CLR</category>
      <category>Delegates</category>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=9145f690-7279-47b9-95cc-b439660402ad</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,9145f690-7279-47b9-95cc-b439660402ad.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,9145f690-7279-47b9-95cc-b439660402ad.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=9145f690-7279-47b9-95cc-b439660402ad</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
After my last few CLR posts, I've had a couple of private inquiries regarding the
usefulness of closed static delegates.  To bring everyone up to speed, a delegate
pointing to an instance method needs a "target" instance to operate on (we'll get
to <em>open instance</em> delegates later).  A static method, needs no such target,
so we can leverage the "space" used for the instance case to carry around another
object of interest.  We call a delegate with a provided value for this space
"closed over the first argument".
</p>
        <p>
For example, let's say we have a static method that does some operation on two numbers. 
For simplicity, let's just say it adds them.  Our silly class and method might
look like this:
</p>
        <blockquote>
          <pre>
            <span style="COLOR: #0000ff">public</span>
            <span style="COLOR: #0000ff">static</span>
            <span style="COLOR: #0000ff">class</span> NumberFunctions
{ <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #0000ff">double</span> Add(<span style="COLOR: #0000ff">double</span> first, <span style="COLOR: #0000ff">double</span> second)
{ <span style="COLOR: #0000ff">return</span> first + second; } }</pre>
        </blockquote>
        <p>
        </p>
        <p>
Normally, a delegate for this method would look like:
</p>
        <blockquote>
          <pre>
            <span style="COLOR: #0000ff">public</span>
            <span style="COLOR: #0000ff">delegate</span>
            <span style="COLOR: #0000ff">double</span> BinaryOperation(<span style="COLOR: #0000ff">double</span> first, <span style="COLOR: #0000ff">double</span> second);</pre>
        </blockquote>
        <p>
But, we're going to create a closed static delegate, which means we're going to "burn"
the first argument into the delegate itself, so it's not needed in the delegate signature. 
Instead, we'll use the following delegate signature (I didn't spend much time thinking
up these names, I hope they make sense:
</p>
        <blockquote>
          <pre>
            <span style="COLOR: #0000ff">public</span>
            <span style="COLOR: #0000ff">delegate</span>
            <span style="COLOR: #0000ff">double</span> ClosedCall(<span style="COLOR: #0000ff">double</span> other);</pre>
        </blockquote>
        <p>
So, how do we create the delegate?  Normally, since C# (pre-Orcas) doesn't have
syntax for creating closed static delegates, you are forced to use one of the <a href="http://www.marklio.com/marklio/ct.ashx?id=9145f690-7279-47b9-95cc-b439660402ad&amp;url=http%3a%2f%2fmsdn2.microsoft.com%2fen-us%2flibrary%2fsystem.delegate.createdelegate.aspx" target="_blank">Delegate.CreateDelegate</a> overloads:
</p>
        <blockquote>
          <pre>ClosedCall addToOne = (ClosedCall)Delegate.CreateDelegate(
        <span style="COLOR: #0000ff">typeof</span>(ClosedCall),
1.0, <span style="COLOR: #0000ff">typeof</span>(NumberFunctions).GetMethod("<span style="COLOR: #8b0000">Add</span>",
BindingFlags.Public | BindingFlags.Static)); </pre>
        </blockquote>
        <p>
Of course, we just spent <a href="http://www.marklio.com/marklio/ct.ashx?id=9145f690-7279-47b9-95cc-b439660402ad&amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2ccce144d6-e166-45e5-a82a-55594c83e0cb.aspx" target="_blank">2</a><a href="http://www.marklio.com/marklio/ct.ashx?id=9145f690-7279-47b9-95cc-b439660402ad&amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2c3df80b83-9191-4495-9d9f-b6238d06f883.aspx" target="_blank">entries</a> looking
at a helper that can do this for us (I'm not claiming this is better, I just want
you to be able to see what's happening):
</p>
        <blockquote>
          <pre>ClosedCall addToOne = DelegateBinder.Bind&lt;ClosedCall&gt;(1.0,
        <span style="COLOR: #0000ff">typeof</span>(NumberFunctions).GetMethod("<span style="COLOR: #8b0000">Add</span>",
BindingFlags.Public | BindingFlags.Static));</pre>
        </blockquote>
        <p>
Now, a call to addToOne(someNumber) will yield the result of adding the supplied argument
to one.  This is a contrived example, but you could imagine taking a method (perhaps
generated on the fly via LCG), and "attaching" an instance to it via the first argument. 
Then, being able to call it many times with different subsequent arguments, or passing
it to another component that would provide the rest of the arguments.  In this
way, you get the benefits of not having to keep track of an instance, without having
to own the API for the instance.  Additionally, you could "chain" delegates together
so that many arguments are captured in a stack of delegate calls, allowing closure-type
semantics at the cost of some stack space (although since C# has closure support,
you'd never really need to do that).
</p>
        <p>
What's really cool is that with C# 3.0's <a href="http://www.marklio.com/marklio/ct.ashx?id=9145f690-7279-47b9-95cc-b439660402ad&amp;url=http%3a%2f%2fweblogs.asp.net%2fscottgu%2farchive%2f2007%2f03%2f13%2fnew-orcas-language-feature-extension-methods.aspx" target="_blank">Extension
Methods</a> feature, we now have language support for creating early-bound closed-static
delegates.  If you bind a delegate to an extension method (using the regular
syntax for an instance method), you will get the exact IL for creating an early-bound closed
static method <strong>without our fancy helper class</strong>.  Let's see how
that would look.  Let's use a different example to keep us on our toes. 
Here's a helper function that creates email addresses:
</p>
        <blockquote>
          <pre>
            <span style="COLOR: #0000ff">public</span>
            <span style="COLOR: #0000ff">static</span>
            <span style="COLOR: #0000ff">class</span> StringExtensions
{ <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #0000ff">string</span> MakeEmailAddressWithAlias(<span style="COLOR: #0000ff">this</span><span style="COLOR: #0000ff">string</span> domain, <span style="COLOR: #0000ff">string</span> alias)
{ <span style="COLOR: #0000ff">return</span><span style="COLOR: #0000ff">string</span>.Format("<span style="COLOR: #8b0000">{0}@{1}</span>",
alias, domain); } }</pre>
        </blockquote>
        <p>
Notice the "this" in front of the first parameter, this tells the compiler that the
method should be considered when resolving method calls for string.  We'll use
one of the delegate types provided in Orcas. Now, here's how the bind looks:
</p>
        <blockquote>
          <pre>
            <span style="COLOR: #0000ff">string</span> fooDotCom = "<span style="COLOR: #8b0000">foo.com</span>";
Func&lt;<span style="COLOR: #0000ff">string</span>, <span style="COLOR: #0000ff">string</span>&gt;
makeFooDotComAddress = fooDotCom.MakeEmailAddressWithAlias; <span style="COLOR: #0000ff">string</span> email
= makeFooDotComAddress("<span style="COLOR: #8b0000">bar</span>");</pre>
        </blockquote>
        <p>
So, the result is that email will be <a href="mailto:bar@foo.com">bar@foo.com</a>.
</p>
        <p>
Hopefully, through these contrived examples, you can see the scenarios that closed
static methods provide, as well as learn how you can create one the easy way with
extension methods in Orcas.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=9145f690-7279-47b9-95cc-b439660402ad" />
      </body>
      <title>What can you do with a closed static delegate? (and how to create them with Orcas)</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,9145f690-7279-47b9-95cc-b439660402ad.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,9145f690-7279-47b9-95cc-b439660402ad.aspx</link>
      <pubDate>Thu, 17 May 2007 17:46:22 GMT</pubDate>
      <description>&lt;p&gt;
After my last few CLR posts, I've had a couple of private inquiries regarding the
usefulness of closed static delegates.&amp;nbsp; To bring everyone up to speed, a delegate
pointing to an instance method needs a "target" instance to operate on (we'll get
to &lt;em&gt;open instance&lt;/em&gt; delegates later).&amp;nbsp; A static method, needs no such target,
so we can leverage the "space" used for the instance case to carry around another
object of interest.&amp;nbsp; We call a delegate with a provided value for this space
"closed over the first argument".
&lt;/p&gt;
&lt;p&gt;
For example, let's say we have a static method that does some operation on two numbers.&amp;nbsp;
For simplicity, let's just say it adds them.&amp;nbsp; Our silly class and method might
look like this:
&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;class&lt;/span&gt; NumberFunctions
{ &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;double&lt;/span&gt; Add(&lt;span style="COLOR: #0000ff"&gt;double&lt;/span&gt; first, &lt;span style="COLOR: #0000ff"&gt;double&lt;/span&gt; second)
{ &lt;span style="COLOR: #0000ff"&gt;return&lt;/span&gt; first + second; } }&lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
Normally, a delegate for this method would look like:
&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;delegate&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;double&lt;/span&gt; BinaryOperation(&lt;span style="COLOR: #0000ff"&gt;double&lt;/span&gt; first, &lt;span style="COLOR: #0000ff"&gt;double&lt;/span&gt; second);&lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
But, we're going to create a closed static delegate, which means we're going to "burn"
the first argument into the delegate itself, so it's not needed in the delegate signature.&amp;nbsp;
Instead, we'll use the following delegate signature (I didn't spend much time thinking
up these names, I hope they make sense:
&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;delegate&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;double&lt;/span&gt; ClosedCall(&lt;span style="COLOR: #0000ff"&gt;double&lt;/span&gt; other);&lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
So, how do we create the delegate?&amp;nbsp; Normally, since C# (pre-Orcas) doesn't have
syntax&amp;nbsp;for creating closed static delegates, you are forced to use one of the &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=9145f690-7279-47b9-95cc-b439660402ad&amp;amp;url=http%3a%2f%2fmsdn2.microsoft.com%2fen-us%2flibrary%2fsystem.delegate.createdelegate.aspx" target=_blank&gt;Delegate.CreateDelegate&lt;/a&gt; overloads:
&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;ClosedCall addToOne = (ClosedCall)Delegate.CreateDelegate(
        &lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(ClosedCall),
1.0, &lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(NumberFunctions).GetMethod("&lt;span style="COLOR: #8b0000"&gt;Add&lt;/span&gt;",
BindingFlags.Public | BindingFlags.Static)); &lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
Of course, we just spent &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=9145f690-7279-47b9-95cc-b439660402ad&amp;amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2ccce144d6-e166-45e5-a82a-55594c83e0cb.aspx" target=_blank&gt;2&lt;/a&gt; &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=9145f690-7279-47b9-95cc-b439660402ad&amp;amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2c3df80b83-9191-4495-9d9f-b6238d06f883.aspx" target=_blank&gt;entries&lt;/a&gt; looking
at a helper that can do this for us (I'm not claiming this is better, I just want
you to be able to see what's happening):
&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;ClosedCall addToOne = DelegateBinder.Bind&amp;lt;ClosedCall&amp;gt;(1.0,
        &lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(NumberFunctions).GetMethod("&lt;span style="COLOR: #8b0000"&gt;Add&lt;/span&gt;",
BindingFlags.Public | BindingFlags.Static));&lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
Now, a call to addToOne(someNumber) will yield the result of adding the supplied argument
to one.&amp;nbsp; This is a contrived example, but you could imagine taking a method (perhaps
generated on the fly via LCG), and "attaching" an instance to it via the first argument.&amp;nbsp;
Then, being able to call it many times with different subsequent arguments, or passing
it to another component that would provide the rest of the arguments.&amp;nbsp; In this
way, you get the benefits of not having to keep track of an instance, without&amp;nbsp;having
to own the API for the instance.&amp;nbsp; Additionally, you could "chain" delegates together
so that many arguments are captured in a stack of delegate calls, allowing closure-type
semantics at the cost of some stack space (although since C# has closure support,
you'd never really need to do that).
&lt;/p&gt;
&lt;p&gt;
What's really cool is that with C# 3.0's &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=9145f690-7279-47b9-95cc-b439660402ad&amp;amp;url=http%3a%2f%2fweblogs.asp.net%2fscottgu%2farchive%2f2007%2f03%2f13%2fnew-orcas-language-feature-extension-methods.aspx" target=_blank&gt;Extension
Methods&lt;/a&gt;&amp;nbsp;feature, we now have language support for creating early-bound closed-static
delegates.&amp;nbsp; If you bind a delegate to an extension method (using the regular
syntax for an instance method), you will get the exact IL for creating an early-bound&amp;nbsp;closed
static method &lt;strong&gt;without our fancy helper class&lt;/strong&gt;.&amp;nbsp; Let's see how
that would look.&amp;nbsp; Let's use a different example to keep us on our toes.&amp;nbsp;
Here's a helper function that creates email addresses:
&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;class&lt;/span&gt; StringExtensions
{ &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt; MakeEmailAddressWithAlias(&lt;span style="COLOR: #0000ff"&gt;this&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt; domain, &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt; alias)
{ &lt;span style="COLOR: #0000ff"&gt;return&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt;.Format("&lt;span style="COLOR: #8b0000"&gt;{0}@{1}&lt;/span&gt;",
alias, domain); } }&lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
Notice the "this" in front of the first parameter, this tells the compiler that the
method should be considered when resolving method calls for string.&amp;nbsp; We'll use
one of the delegate types provided in Orcas. Now, here's how the bind looks:
&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt; fooDotCom = "&lt;span style="COLOR: #8b0000"&gt;foo.com&lt;/span&gt;";
Func&amp;lt;&lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt;, &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt;&amp;gt;
makeFooDotComAddress = fooDotCom.MakeEmailAddressWithAlias; &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt; email
= makeFooDotComAddress("&lt;span style="COLOR: #8b0000"&gt;bar&lt;/span&gt;");&lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
So, the result is that email will be &lt;a href="mailto:bar@foo.com"&gt;bar@foo.com&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Hopefully, through these contrived examples, you can see the scenarios that closed
static methods provide, as well as learn how you can create one the easy way with
extension methods in Orcas.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=9145f690-7279-47b9-95cc-b439660402ad" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,9145f690-7279-47b9-95cc-b439660402ad.aspx</comments>
      <category>CLR</category>
      <category>Delegates</category>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=3df80b83-9191-4495-9d9f-b6238d06f883</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,3df80b83-9191-4495-9d9f-b6238d06f883.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,3df80b83-9191-4495-9d9f-b6238d06f883.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=3df80b83-9191-4495-9d9f-b6238d06f883</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
In <a href="http://www.marklio.com/marklio/ct.ashx?id=3df80b83-9191-4495-9d9f-b6238d06f883&amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2ccce144d6-e166-45e5-a82a-55594c83e0cb.aspx" target="_blank">my
last post</a>, I showed a nifty way of constructing "early-bound" delegates using
LCG.  Here's the same helper class implemented without LCG:
</p>
        <blockquote>
          <pre>
            <span style="COLOR: #0000ff">public</span>
            <span style="COLOR: #0000ff">static</span>
            <span style="COLOR: #0000ff">class</span> DelegateBinder
{ <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">static</span> TDelegate
Bind&lt;TDelegate&gt;(<span style="COLOR: #0000ff">object</span> firstArg, MethodInfo
method) { <span style="COLOR: #0000ff">return</span> (TDelegate)Activator.CreateInstance( <span style="COLOR: #0000ff">typeof</span>(TDelegate),
firstArg, method.MethodHandle.GetFunctionPointer()); } } </pre>
        </blockquote>
        <p>
This one is quite a bit simpler, and extrapolating from what we learned last time,
it's easy to see what's happening.  Hopefully, you are already familiar
with the <a href="http://www.marklio.com/marklio/ct.ashx?id=3df80b83-9191-4495-9d9f-b6238d06f883&amp;url=http%3a%2f%2fmsdn2.microsoft.com%2fen-us%2flibrary%2fsystem.activator.aspx" target="_blank">Activator</a> class. 
Basically, this just shows the managed call chain that produces a function pointer
to a method given a MethodInfo.
</p>
        <p>
I really like the LCG-based implementation, but only because of my love of DynamicMethod. 
It's pretty complex, and aside from opportunities for caching, doesn't really have
anything over this implementation. This one is just plain simple, and would have a
single-line implementation if I hadn't put some line breaks to avoid formatting problems. 
It does, however, highlight the annoyingness of having to work around the compilers' "helpfulness"
when it comes to delegate construction.  If only I could just call the constructor
directly.
</p>
        <p>
It is worth noting that this doesn't work in the Silverlight 1.1 alpha or the compact
framework (or XNA for that matter), neither of which expose <a href="http://www.marklio.com/marklio/ct.ashx?id=3df80b83-9191-4495-9d9f-b6238d06f883&amp;url=http%3a%2f%2fmsdn2.microsoft.com%2fen-us%2flibrary%2fsystem.runtimemethodhandle.getfunctionpointer.aspx" target="_blank">RuntimeMethodHandle.GetFunctionPointer()</a>.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=3df80b83-9191-4495-9d9f-b6238d06f883" />
      </body>
      <title>Early-bind delegates without LCG</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,3df80b83-9191-4495-9d9f-b6238d06f883.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,3df80b83-9191-4495-9d9f-b6238d06f883.aspx</link>
      <pubDate>Mon, 14 May 2007 23:40:01 GMT</pubDate>
      <description>&lt;p&gt;
In &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=3df80b83-9191-4495-9d9f-b6238d06f883&amp;amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2ccce144d6-e166-45e5-a82a-55594c83e0cb.aspx" target=_blank&gt;my
last post&lt;/a&gt;, I showed a nifty way of constructing "early-bound" delegates using
LCG.&amp;nbsp; Here's the same helper class implemented without LCG:
&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;class&lt;/span&gt; DelegateBinder
{ &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; TDelegate
Bind&amp;lt;TDelegate&amp;gt;(&lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt; firstArg, MethodInfo
method) { &lt;span style="COLOR: #0000ff"&gt;return&lt;/span&gt; (TDelegate)Activator.CreateInstance( &lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(TDelegate),
firstArg, method.MethodHandle.GetFunctionPointer()); } } &lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
This one is quite a bit simpler, and extrapolating from what we learned last time,
it's easy to see what's happening.&amp;nbsp; Hopefully, you are already&amp;nbsp;familiar
with the &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=3df80b83-9191-4495-9d9f-b6238d06f883&amp;amp;url=http%3a%2f%2fmsdn2.microsoft.com%2fen-us%2flibrary%2fsystem.activator.aspx" target=_blank&gt;Activator&lt;/a&gt; class.&amp;nbsp;
Basically, this just shows the managed call chain that produces a function pointer
to a method given a MethodInfo.
&lt;/p&gt;
&lt;p&gt;
I really like the LCG-based implementation, but only because of my love of DynamicMethod.&amp;nbsp;
It's pretty complex, and aside from opportunities for caching, doesn't really have
anything over this implementation. This one is just plain simple, and would have a
single-line implementation if I hadn't put some line breaks to avoid formatting problems.&amp;nbsp;
It does, however, highlight the annoyingness of having to work around the compilers'&amp;nbsp;"helpfulness"
when it comes to delegate construction.&amp;nbsp; If only I could just call the constructor
directly.
&lt;/p&gt;
&lt;p&gt;
It is worth noting that this doesn't work in the Silverlight 1.1 alpha or the compact
framework (or XNA for that matter), neither of which expose &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=3df80b83-9191-4495-9d9f-b6238d06f883&amp;amp;url=http%3a%2f%2fmsdn2.microsoft.com%2fen-us%2flibrary%2fsystem.runtimemethodhandle.getfunctionpointer.aspx" target=_blank&gt;RuntimeMethodHandle.GetFunctionPointer()&lt;/a&gt;.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=3df80b83-9191-4495-9d9f-b6238d06f883" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,3df80b83-9191-4495-9d9f-b6238d06f883.aspx</comments>
      <category>CLR</category>
      <category>Delegates</category>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=cce144d6-e166-45e5-a82a-55594c83e0cb</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,cce144d6-e166-45e5-a82a-55594c83e0cb.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,cce144d6-e166-45e5-a82a-55594c83e0cb.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=cce144d6-e166-45e5-a82a-55594c83e0cb</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
In a <a href="http://www.marklio.com/marklio/ct.ashx?id=cce144d6-e166-45e5-a82a-55594c83e0cb&amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2c4269ecd2-381c-4ab0-ae2e-7e88ed706977.aspx" target="_blank">previous
post about delegates</a>, I discussed the following interesting cases of delegates:
</p>
        <ul>
          <li>
Closed static 
</li>
          <li>
Open instance</li>
        </ul>
        <p>
See the previous post for the full explanation, but these basically open up some interesting
dynamic scenarios.  The problem is that C# and VB do not expose syntax for constructing
these in an "early-bound" fashion, that is using the special constructor on the delegate
type rather than Delegate.CreateDelegate (which more or less binds via reflection).
</p>
        <p>
For most scenarios this is not a huge problem, but there are some performance considerations
and other issues to consider that I don't really want to dig into at the moment. 
One sufficiently important scenario is <em><strong>testing</strong></em> early-bound
invocation.  If your language doesn't support something, how can you test it? 
Well, you can write the whole test in IL, but that is not a terribly maintainable
proposition.
</p>
        <p>
Another option is to only write the part you need in IL.  Unfortunately, C# doesn't
allow you to write inline IL, but you can use Reflection.Emit.  And, since v2.0,
you can use LCG (Lightweight Code Generation) via DynamicMethod.
</p>
        <p>
The trick here is to understand how delegates are instantiated.  Delegates are
just classes like any other.  They inherit from MulticastDelegate (typically). 
The special part is that the runtime provides all the implementation and they have
a special constructor.  Here's (approximately) the constructor signature
for System.Action&lt;T&gt;:
</p>
        <blockquote>
          <pre>
            <span style="COLOR: #0000ff">public</span> Action(<span style="COLOR: #0000ff">object</span> o,
IntPtr method)</pre>
        </blockquote>
        <p>
Object? IntPtr?  What the heck? Well, it's not as bizarre as you might think. 
The object is simply the first argument for the invocation.  This allows binding
to a particular instance ("this" for instance methods, arg 0 for static methods).
The IntPtr is a pointer to the method.  "Pointers?!!?!?! in managed code?!?!"
you say?  That's right, a pointer.  An object is easy enough to come by,
but where do I get the pointer?  Well, the pointer can be easily retrieved via
the <a href="http://www.marklio.com/marklio/ct.ashx?id=cce144d6-e166-45e5-a82a-55594c83e0cb&amp;url=http%3a%2f%2fmsdn2.microsoft.com%2fen-us%2flibrary%2fsystem.reflection.emit.opcodes.ldftn.aspx" target="_blank">ldftn</a> opcode. 
It loads the address of a given method (described via a token in IL, and a MethodInfo
in Reflection.Emit).
</p>
        <p>
Lets cut to the chase.  Here's a little class that can bind a method to a delegate
type and allow you to provide the first argument (you'll need System, System.Reflection,
System.Reflection.Emit using statements):
</p>
        <blockquote>
          <pre>
            <span style="COLOR: #0000ff">public</span>
            <span style="COLOR: #0000ff">static</span>
            <span style="COLOR: #0000ff">class</span> DelegateBinder
{ <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">delegate</span> TDelegate
Binder&lt;TDelegate&gt;(<span style="COLOR: #0000ff">object</span> firstArg); <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">static</span> TDelegate
Bind&lt;TDelegate&gt;(<span style="COLOR: #0000ff">object</span> firstArg, MethodInfo
method) { DynamicMethod dynMethod = <span style="COLOR: #0000ff">new</span> DynamicMethod("<span style="COLOR: #8b0000">PassthroughBinderImplementation</span>", <span style="COLOR: #0000ff">typeof</span>(TDelegate), <span style="COLOR: #0000ff">new</span> Type[]
{ <span style="COLOR: #0000ff">typeof</span>(<span style="COLOR: #0000ff">object</span>)
}, <span style="COLOR: #0000ff">typeof</span>(DelegateBinder)); ILGenerator gen =
dynMethod.GetILGenerator(); <span style="COLOR: #008000">//load the first argument</span> gen.Emit(OpCodes.Ldarg_0); <span style="COLOR: #008000">//load
the address of the method</span> gen.Emit(OpCodes.Ldftn, method); <span style="COLOR: #008000">//create
the delegate</span> gen.Emit(OpCodes.Newobj, <span style="COLOR: #0000ff">typeof</span>(TDelegate).GetConstructor(<span style="COLOR: #0000ff">new</span> Type[]
{ <span style="COLOR: #0000ff">typeof</span>(<span style="COLOR: #0000ff">object</span>), <span style="COLOR: #0000ff">typeof</span>(IntPtr)
})); gen.Emit(OpCodes.Ret); <span style="COLOR: #0000ff">return</span> ((Binder&lt;TDelegate&gt;)dynMethod.CreateDelegate(<span style="COLOR: #0000ff">typeof</span>(Binder&lt;TDelegate&gt;)))(firstArg);
} } </pre>
        </blockquote>
        <p>
With this class, you can dynamically construct all the early-bound variants (ignoring
variants for signature relaxation) like so:
</p>
        <blockquote>
          <pre>
            <span style="COLOR: #0000ff">using</span> System; <span style="COLOR: #0000ff">using</span> System.Reflection; <span style="COLOR: #0000ff">using</span> System.Reflection.Emit; <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">delegate</span><span style="COLOR: #0000ff">string</span> Passthrough(<span style="COLOR: #0000ff">string</span> str); <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">delegate</span><span style="COLOR: #0000ff">string</span> BoundPassthrough(); <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">delegate</span><span style="COLOR: #0000ff">string</span> ProgramPassthrough(Program
p); <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">class</span> Program
{ <span style="COLOR: #0000ff">static</span><span style="COLOR: #0000ff">void</span> Main(<span style="COLOR: #0000ff">string</span>[]
args) { Console.WriteLine("<span style="COLOR: #8b0000">Open Static:</span>"); Passthrough
ospt = DelegateBinder.Bind&lt;Passthrough&gt;(<span style="COLOR: #0000ff">null</span>, <span style="COLOR: #0000ff">typeof</span>(Program).GetMethod("<span style="COLOR: #8b0000">StaticImplementation</span>", <span style="COLOR: #0000ff">new</span> Type[]
{ <span style="COLOR: #0000ff">typeof</span>(<span style="COLOR: #0000ff">string</span>)
})); Console.WriteLine(ospt("<span style="COLOR: #8b0000">Hello World</span>")); Console.WriteLine("<span style="COLOR: #8b0000">Closed
static:</span>"); BoundPassthrough cspt = DelegateBinder.Bind&lt;BoundPassthrough&gt;("<span style="COLOR: #8b0000">Hello
World</span>", <span style="COLOR: #0000ff">typeof</span>(Program).GetMethod("<span style="COLOR: #8b0000">StaticImplementation</span>", <span style="COLOR: #0000ff">new</span> Type[]
{ <span style="COLOR: #0000ff">typeof</span>(<span style="COLOR: #0000ff">string</span>)
})); Console.WriteLine(cspt()); Console.WriteLine("<span style="COLOR: #8b0000">Open
Instance:</span>"); ProgramPassthrough oipt = DelegateBinder.Bind&lt;ProgramPassthrough&gt;(<span style="COLOR: #0000ff">null</span>, <span style="COLOR: #0000ff">typeof</span>(Program).GetMethod("<span style="COLOR: #8b0000">InstanceImplementation</span>",
Type.EmptyTypes)); Console.WriteLine(oipt(<span style="COLOR: #0000ff">new</span> Program("<span style="COLOR: #8b0000">Hello
World</span>"))); Console.WriteLine("<span style="COLOR: #8b0000">Closed Instance:</span>");
BoundPassthrough cipt = DelegateBinder.Bind&lt;BoundPassthrough&gt;(<span style="COLOR: #0000ff">new</span> Program("<span style="COLOR: #8b0000">Hello
World</span>"), <span style="COLOR: #0000ff">typeof</span>(Program).GetMethod("<span style="COLOR: #8b0000">InstanceImplementation</span>",
Type.EmptyTypes)); Console.WriteLine(cipt()); } <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #0000ff">string</span> StaticImplementation(<span style="COLOR: #0000ff">string</span> str)
{ <span style="COLOR: #0000ff">return</span> str; } <span style="COLOR: #0000ff">public</span> Program(<span style="COLOR: #0000ff">string</span> payload)
{ _Payload = payload; } <span style="COLOR: #0000ff">string</span> _Payload; <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">string</span> InstanceImplementation()
{ <span style="COLOR: #0000ff">return</span> _Payload; } }</pre>
        </blockquote>
        <p>
So, there are certainly cases that will break this, most involving incompatible signature
issues between the method, delegate, and the first argument.  But I didn't want
to make things more complicated for an example. Besides, the point of this is not
really to give you some neat tool (you'll probably never need to do this), but to
give people a better idea what the compiler is doing for you when you create a delegate.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=cce144d6-e166-45e5-a82a-55594c83e0cb" />
      </body>
      <title>Early-bound delegates via LCG</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,cce144d6-e166-45e5-a82a-55594c83e0cb.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,cce144d6-e166-45e5-a82a-55594c83e0cb.aspx</link>
      <pubDate>Fri, 11 May 2007 22:54:23 GMT</pubDate>
      <description>&lt;p&gt;
In a &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=cce144d6-e166-45e5-a82a-55594c83e0cb&amp;amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2c4269ecd2-381c-4ab0-ae2e-7e88ed706977.aspx" target=_blank&gt;previous
post about delegates&lt;/a&gt;, I discussed the following interesting cases of delegates:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Closed static 
&lt;li&gt;
Open instance&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
See the previous post for the full explanation, but these basically open up some interesting
dynamic scenarios.&amp;nbsp; The problem is that C# and VB do not expose syntax for constructing
these in an "early-bound" fashion, that is using the special constructor on the delegate
type rather than Delegate.CreateDelegate (which more or less binds via reflection).
&lt;/p&gt;
&lt;p&gt;
For most scenarios this is not a huge problem, but there are some performance considerations
and other issues to consider that I don't really want to dig into at the moment.&amp;nbsp;
One sufficiently important scenario is &lt;em&gt;&lt;strong&gt;testing&lt;/strong&gt;&lt;/em&gt; early-bound
invocation.&amp;nbsp; If your language doesn't support something, how can you test it?&amp;nbsp;
Well, you can write the whole test in IL, but that is not a terribly maintainable
proposition.
&lt;/p&gt;
&lt;p&gt;
Another option is to only write the part you need in IL.&amp;nbsp; Unfortunately, C# doesn't
allow you to write inline IL, but you can use Reflection.Emit.&amp;nbsp; And, since v2.0,
you can use LCG (Lightweight Code Generation) via DynamicMethod.
&lt;/p&gt;
&lt;p&gt;
The trick here is to understand how delegates are instantiated.&amp;nbsp; Delegates are
just classes like any other.&amp;nbsp; They inherit from MulticastDelegate (typically).&amp;nbsp;
The special part is that the runtime provides all the implementation and they have
a special constructor.&amp;nbsp;&amp;nbsp;Here's (approximately) the constructor signature
for System.Action&amp;lt;T&amp;gt;:
&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; Action(&lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt; o,
IntPtr method)&lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
Object? IntPtr?&amp;nbsp; What the heck? Well, it's not as bizarre as you might think.&amp;nbsp;
The object is simply the first argument for the invocation.&amp;nbsp; This allows binding
to a particular instance ("this" for instance methods, arg 0 for static methods).
The IntPtr is a pointer to the method.&amp;nbsp; "Pointers?!!?!?! in managed code?!?!"
you say?&amp;nbsp; That's right, a pointer.&amp;nbsp; An object is easy enough to come by,
but where do I get the pointer?&amp;nbsp; Well, the pointer can be easily retrieved via
the &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=cce144d6-e166-45e5-a82a-55594c83e0cb&amp;amp;url=http%3a%2f%2fmsdn2.microsoft.com%2fen-us%2flibrary%2fsystem.reflection.emit.opcodes.ldftn.aspx" target=_blank&gt;ldftn&lt;/a&gt; opcode.&amp;nbsp;
It loads the address of a given method (described via a token in IL, and a MethodInfo
in Reflection.Emit).
&lt;/p&gt;
&lt;p&gt;
Lets cut to the chase.&amp;nbsp; Here's a little class that can bind a method to a delegate
type and allow you to provide the first argument (you'll need System, System.Reflection,
System.Reflection.Emit using statements):
&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;class&lt;/span&gt; DelegateBinder
{ &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;delegate&lt;/span&gt; TDelegate
Binder&amp;lt;TDelegate&amp;gt;(&lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt; firstArg); &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; TDelegate
Bind&amp;lt;TDelegate&amp;gt;(&lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt; firstArg, MethodInfo
method) { DynamicMethod dynMethod = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; DynamicMethod("&lt;span style="COLOR: #8b0000"&gt;PassthroughBinderImplementation&lt;/span&gt;", &lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(TDelegate), &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; Type[]
{ &lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(&lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt;)
}, &lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(DelegateBinder)); ILGenerator gen =
dynMethod.GetILGenerator(); &lt;span style="COLOR: #008000"&gt;//load the first argument&lt;/span&gt; gen.Emit(OpCodes.Ldarg_0); &lt;span style="COLOR: #008000"&gt;//load
the address of the method&lt;/span&gt; gen.Emit(OpCodes.Ldftn, method); &lt;span style="COLOR: #008000"&gt;//create
the delegate&lt;/span&gt; gen.Emit(OpCodes.Newobj, &lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(TDelegate).GetConstructor(&lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; Type[]
{ &lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(&lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt;), &lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(IntPtr)
})); gen.Emit(OpCodes.Ret); &lt;span style="COLOR: #0000ff"&gt;return&lt;/span&gt; ((Binder&amp;lt;TDelegate&amp;gt;)dynMethod.CreateDelegate(&lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(Binder&amp;lt;TDelegate&amp;gt;)))(firstArg);
} } &lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
With this class, you can dynamically&amp;nbsp;construct all the early-bound variants (ignoring
variants for signature relaxation) like so:
&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt; System; &lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt; System.Reflection; &lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt; System.Reflection.Emit; &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;delegate&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt; Passthrough(&lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt; str); &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;delegate&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt; BoundPassthrough(); &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;delegate&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt; ProgramPassthrough(Program
p); &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;class&lt;/span&gt; Program
{ &lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; Main(&lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt;[]
args) { Console.WriteLine("&lt;span style="COLOR: #8b0000"&gt;Open Static:&lt;/span&gt;"); Passthrough
ospt = DelegateBinder.Bind&amp;lt;Passthrough&amp;gt;(&lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;, &lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(Program).GetMethod("&lt;span style="COLOR: #8b0000"&gt;StaticImplementation&lt;/span&gt;", &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; Type[]
{ &lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(&lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt;)
})); Console.WriteLine(ospt("&lt;span style="COLOR: #8b0000"&gt;Hello World&lt;/span&gt;")); Console.WriteLine("&lt;span style="COLOR: #8b0000"&gt;Closed
static:&lt;/span&gt;"); BoundPassthrough cspt = DelegateBinder.Bind&amp;lt;BoundPassthrough&amp;gt;("&lt;span style="COLOR: #8b0000"&gt;Hello
World&lt;/span&gt;", &lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(Program).GetMethod("&lt;span style="COLOR: #8b0000"&gt;StaticImplementation&lt;/span&gt;", &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; Type[]
{ &lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(&lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt;)
})); Console.WriteLine(cspt()); Console.WriteLine("&lt;span style="COLOR: #8b0000"&gt;Open
Instance:&lt;/span&gt;"); ProgramPassthrough oipt = DelegateBinder.Bind&amp;lt;ProgramPassthrough&amp;gt;(&lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;, &lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(Program).GetMethod("&lt;span style="COLOR: #8b0000"&gt;InstanceImplementation&lt;/span&gt;",
Type.EmptyTypes)); Console.WriteLine(oipt(&lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; Program("&lt;span style="COLOR: #8b0000"&gt;Hello
World&lt;/span&gt;"))); Console.WriteLine("&lt;span style="COLOR: #8b0000"&gt;Closed Instance:&lt;/span&gt;");
BoundPassthrough cipt = DelegateBinder.Bind&amp;lt;BoundPassthrough&amp;gt;(&lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; Program("&lt;span style="COLOR: #8b0000"&gt;Hello
World&lt;/span&gt;"), &lt;span style="COLOR: #0000ff"&gt;typeof&lt;/span&gt;(Program).GetMethod("&lt;span style="COLOR: #8b0000"&gt;InstanceImplementation&lt;/span&gt;",
Type.EmptyTypes)); Console.WriteLine(cipt()); } &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt; StaticImplementation(&lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt; str)
{ &lt;span style="COLOR: #0000ff"&gt;return&lt;/span&gt; str; } &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; Program(&lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt; payload)
{ _Payload = payload; } &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt; _Payload; &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt; InstanceImplementation()
{ &lt;span style="COLOR: #0000ff"&gt;return&lt;/span&gt; _Payload; } }&lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
So, there are certainly cases that will break this, most involving incompatible signature
issues between the method, delegate, and the first argument.&amp;nbsp; But I didn't want
to make things more complicated for an example. Besides, the point of this is not
really to give you some neat tool (you'll probably never need to do this), but to
give people a better idea what the compiler is doing for you when you create a delegate.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=cce144d6-e166-45e5-a82a-55594c83e0cb" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,cce144d6-e166-45e5-a82a-55594c83e0cb.aspx</comments>
      <category>CLR</category>
      <category>Delegates</category>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=d22679fc-6291-4b13-a9bb-36f0fb55d364</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,d22679fc-6291-4b13-a9bb-36f0fb55d364.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,d22679fc-6291-4b13-a9bb-36f0fb55d364.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=d22679fc-6291-4b13-a9bb-36f0fb55d364</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
A quickie here. I had written some code in javascript to simplify testing of
a fairly dense, multi-dimensional feature area.  I could define the dimensions
I wanted to test declaratively in a more or less JSON fashion and then bang them together
via some enumerable-like extensions that I had written.  Viola, full test matrix
implemented.
</p>
        <p>
Unfortunately, I learned that I would be unable to take a dependency on the scripting
host at run-time.  Too bad I had already invested the time in the solution, and
I would now have to code the matrix myself.  But wait, this is a dynamic language
I'm dealing with!  So, in a short time, I did some object substitution, and now
my javascript is a precompiler that emits C# and other support files that I then compile
to do the same thing.
</p>
        <p>
          <a href="http://www.marklio.com/marklio/ct.ashx?id=d22679fc-6291-4b13-a9bb-36f0fb55d364&amp;url=http%3a%2f%2fwww.nikhilk.net%2f" target="_blank">Nikhil</a> has
a <a href="http://www.marklio.com/marklio/ct.ashx?id=d22679fc-6291-4b13-a9bb-36f0fb55d364&amp;url=http%3a%2f%2fprojects.nikhilk.net%2fProjects%2fScriptSharp.aspx" target="_blank">more
general tool</a> that goes the other way.  It compiles C# into javascript for
use in AJAX apps.  While this is a handy way for people unfamiliar with the power
of dynamic languages to jump into the AJAX world, I'm wondering if it's really a good
idea in the long term.  On the one hand, reducing the number of language dependencies
in a project is good for maintainability, but choosing the less-flexible one seems
like the wrong choice.  Of course javascript has no formal set of class libraries,
so that's a limitation.  Hmmm.  I'll have to think about this some more.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=d22679fc-6291-4b13-a9bb-36f0fb55d364" />
      </body>
      <title>The power of dynamic languages</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,d22679fc-6291-4b13-a9bb-36f0fb55d364.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,d22679fc-6291-4b13-a9bb-36f0fb55d364.aspx</link>
      <pubDate>Wed, 21 Feb 2007 18:05:09 GMT</pubDate>
      <description>&lt;p&gt;
A quickie here. I had written some code in javascript&amp;nbsp;to simplify testing of
a fairly dense, multi-dimensional feature area.&amp;nbsp; I could define the dimensions
I wanted to test declaratively in a more or less JSON fashion and then bang them together
via some enumerable-like extensions that I had written.&amp;nbsp; Viola, full test matrix
implemented.
&lt;/p&gt;
&lt;p&gt;
Unfortunately, I learned that I would be unable to take a dependency on the scripting
host at run-time.&amp;nbsp; Too bad I had already invested the time in the solution, and
I would now have to code the matrix myself.&amp;nbsp; But wait, this is a dynamic language
I'm dealing with!&amp;nbsp; So, in a short time, I did some object substitution, and now
my javascript is a precompiler that emits C# and other support files that I then compile
to do the same thing.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.marklio.com/marklio/ct.ashx?id=d22679fc-6291-4b13-a9bb-36f0fb55d364&amp;amp;url=http%3a%2f%2fwww.nikhilk.net%2f" target="_blank"&gt;Nikhil&lt;/a&gt; has
a &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=d22679fc-6291-4b13-a9bb-36f0fb55d364&amp;amp;url=http%3a%2f%2fprojects.nikhilk.net%2fProjects%2fScriptSharp.aspx" target="_blank"&gt;more
general tool&lt;/a&gt; that goes the other way.&amp;nbsp; It compiles C# into javascript for
use in AJAX apps.&amp;nbsp; While this is a handy way for people unfamiliar with the power
of dynamic languages to jump into the AJAX world, I'm wondering if it's really a good
idea in the long term.&amp;nbsp; On the one hand, reducing the number of language dependencies
in a project is good for maintainability, but choosing the less-flexible one seems
like the wrong choice.&amp;nbsp; Of course javascript has no formal set of class libraries,
so that's a limitation.&amp;nbsp; Hmmm.&amp;nbsp; I'll have to think about this some more.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=d22679fc-6291-4b13-a9bb-36f0fb55d364" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,d22679fc-6291-4b13-a9bb-36f0fb55d364.aspx</comments>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=d65c3e37-70d3-4219-b8b7-34a8423f35e4</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,d65c3e37-70d3-4219-b8b7-34a8423f35e4.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,d65c3e37-70d3-4219-b8b7-34a8423f35e4.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=d65c3e37-70d3-4219-b8b7-34a8423f35e4</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
So, my <a href="http://www.marklio.com/marklio/ct.ashx?id=d65c3e37-70d3-4219-b8b7-34a8423f35e4&amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2c4269ecd2-381c-4ab0-ae2e-7e88ed706977.aspx">last
post</a> talked about delegates.  In it, I mentioned some compiler trickery involved
in declaring events, but I didn't bother explaining it.  After reading it over
again, and getting some feedback, I felt bad about glossing over what is pretty much
the mainline scenario for delegates. So, what is an event?
</p>
        <p>
An event is kind of like a broadcast. It enables an object to notifiy subscribers
when some "event" occurs, give them relevant information about the event, and allow
them to do something in response.  And, you guessed it, delegates are at the
core of making this work.
</p>
        <p>
Fundamentally, events are a callback mechanism, and could be implemented without delegates
using anything from raw function pointers to interfaces, and the CLR doesn't keep
you from doing either of those, but there's value in a consistent pattern.  In
fact, the designers of the CLR felt so strongly about the value of this particular
pattern, that it is part of the <a href="http://www.marklio.com/marklio/ct.ashx?id=d65c3e37-70d3-4219-b8b7-34a8423f35e4&amp;url=http%3a%2f%2fwww.ecma-international.org%2fpublications%2ffiles%2fECMA-ST%2fEcma-335.pdf">CLI
spec</a> (along with properties, another pattern that is implemented by other more
fundamental constructs).
</p>
        <p>
So, how do you make an event?  Well, in C#, you declare an event like you would
declare a field whose type is some delegate and you add the "event" keyword. 
So, somewhere in a type, you would have something like:
</p>
        <blockquote>
          <p>
            <font face="Courier New">public event EventHandler Click;</font>
          </p>
        </blockquote>
        <p>
Whether or not it's public depends on how you expect the event to be used.  EventHandler
is a delegate with the following signature:
</p>
        <blockquote>
          <p>
            <font face="Courier New">void EventHandler(object sender, EventArgs e);</font>
          </p>
        </blockquote>
        <p>
This signature is another pattern that I'll talk about later.  For now, lets
look at what the compiler does for our event declaration.  The compiler gives
3 things (if you don't count the things it already did for the delegate EventHandler):
</p>
        <ul>
          <li>
A private field whose type is the delegate EventHandler 
</li>
          <li>
A (public in this case) method "accessor" for adding delegate callbacks: add_Click
//Click comes from the event name 
</li>
          <li>
A (public in this case) method "accessor" for removing delegate callbacks: remove_Click</li>
        </ul>
        <p>
When other code wants to hook up to your event, they use the += operator on your event. 
This is really syntax sugar for calling the add_Click method.  And, conversely
the -= operator calls the remove accessor.
</p>
        <p>
Interestingly, you can write your own implementation for the event pattern. 
You might want to do this to save size in a possibly large tree structure with
lots of events at each node.  ASP.net does this with controls.  Rather than
every Control having tons of fields for each event, it has a sparse dictionary of
event delegates, that is only populated for events that have "subscribers". 
With a tree that can easily have thousands of controls per page view, this results
in a sizeable savings.  How do you do this?  Well, in C#, you use the little
known syntax:
</p>
        <blockquote>
          <p>
            <font face="Courier New">public event EventHandler Click {</font>
          </p>
          <p>
            <font face="Courier New">add {/* do something with value in here */}</font>
          </p>
        </blockquote>
        <blockquote>
          <p>
            <font face="Courier New">remove {/* do something with value in here */}</font>
          </p>
          <p>
            <font face="Courier New">}</font>
          </p>
        </blockquote>
        <p>
Looks like a property eh? This causes the compiler not to create the 3 things I mentioned
above. Instead, it calls your add and remove accesors to do the adding and removing
(via the value keyword just like properties).  In it, you can do anything you
want, although it's advisable to keep the same semantics as the default implementations.
</p>
        <p>
So, lets talk a little bit about what happens when an event happens and it is called. 
Let's say that several other classes have registered for your event (via the += syntax
or whatever the compiler supports).  Inside your class, you simply call the delegate
(there's a recommended pattern for this as well).  But wait, there's more than
1 subscriber!  Remember, delegates aren't just function pointers, and they are
more powerful than using interfaces alone.  If you'll recall in the last post,
I said that when you create a delegate, you're really getting a MulticastDelegate,
which tracks an invocation list of delegates to run. (this is why the standard event
pattern returns void, otherwise, you've got the weird situation of multiple return
values from what appears to be a single call).  Under normal circumstances, each
delegate in the invocation list is called and execution resumes.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=d65c3e37-70d3-4219-b8b7-34a8423f35e4" />
      </body>
      <title>What is an event?</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,d65c3e37-70d3-4219-b8b7-34a8423f35e4.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,d65c3e37-70d3-4219-b8b7-34a8423f35e4.aspx</link>
      <pubDate>Fri, 16 Feb 2007 18:36:02 GMT</pubDate>
      <description>&lt;p&gt;
So, my &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=d65c3e37-70d3-4219-b8b7-34a8423f35e4&amp;amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2c4269ecd2-381c-4ab0-ae2e-7e88ed706977.aspx"&gt;last
post&lt;/a&gt; talked about delegates.&amp;nbsp; In it, I mentioned some compiler trickery involved
in declaring events, but I didn't bother explaining it.&amp;nbsp; After reading it over
again, and getting some feedback, I felt bad about glossing over what is pretty much
the mainline scenario for delegates. So, what is an event?
&lt;/p&gt;
&lt;p&gt;
An event is kind of like a broadcast. It enables an object to notifiy subscribers
when some "event" occurs, give them relevant information about the event, and allow
them to do something in response.&amp;nbsp; And, you guessed it, delegates are at the
core of making this work.
&lt;/p&gt;
&lt;p&gt;
Fundamentally, events are a callback mechanism, and could be implemented without delegates
using anything from raw function pointers to interfaces, and the CLR doesn't keep
you from doing either of those, but there's value in a consistent pattern.&amp;nbsp; In
fact, the designers of the CLR felt so strongly about the value of this particular
pattern, that it is part of the &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=d65c3e37-70d3-4219-b8b7-34a8423f35e4&amp;amp;url=http%3a%2f%2fwww.ecma-international.org%2fpublications%2ffiles%2fECMA-ST%2fEcma-335.pdf"&gt;CLI
spec&lt;/a&gt; (along with properties, another pattern that is implemented by other more
fundamental constructs).
&lt;/p&gt;
&lt;p&gt;
So, how do you make an event?&amp;nbsp; Well, in C#, you declare an event like you would
declare a field whose type is some delegate and you add the "event" keyword.&amp;nbsp;
So, somewhere in a type, you would have something like:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;public event EventHandler Click;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Whether or not it's public depends on how you expect the event to be used.&amp;nbsp; EventHandler
is a delegate with the following signature:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;void EventHandler(object sender, EventArgs e);&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
This signature is another pattern that I'll talk about later.&amp;nbsp; For now, lets
look at what the compiler does for our event declaration.&amp;nbsp; The compiler gives
3 things (if you don't count the things it already did for the delegate EventHandler):
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
A private field whose type is the delegate EventHandler 
&lt;li&gt;
A (public in this case) method "accessor"&amp;nbsp;for adding delegate callbacks: add_Click
//Click comes from the event name 
&lt;li&gt;
A (public in this case) method "accessor" for removing delegate callbacks: remove_Click&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
When other code wants to hook up to your event, they use the += operator on your event.&amp;nbsp;
This is really syntax sugar for calling the add_Click method.&amp;nbsp; And, conversely
the -= operator calls the remove accessor.
&lt;/p&gt;
&lt;p&gt;
Interestingly, you can write your own implementation for the event pattern.&amp;nbsp;
You might want to do this to save size in&amp;nbsp;a possibly large tree structure with
lots of events at each node.&amp;nbsp; ASP.net does this with controls.&amp;nbsp; Rather than
every Control having tons of fields for each event, it has a sparse dictionary of
event delegates, that is only populated for events that have "subscribers".&amp;nbsp;
With a tree that can easily have thousands of controls per page view, this results
in a sizeable savings.&amp;nbsp; How do you do this?&amp;nbsp; Well, in C#, you use the little
known syntax:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;public event EventHandler Click {&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;add {/* do something with value in here */}&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; &lt;blockquote&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;remove {/* do something with value in here */}&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;}&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Looks like a property eh? This causes the compiler not to create the 3 things I mentioned
above. Instead, it calls your add and remove accesors to do the adding and removing
(via the value keyword just like properties).&amp;nbsp; In it, you can do anything you
want, although it's advisable to keep the same semantics as the default implementations.
&lt;/p&gt;
&lt;p&gt;
So, lets talk a little bit about what happens when an event happens and it is called.&amp;nbsp;
Let's say that several other classes have registered for your event (via the += syntax
or whatever the compiler supports).&amp;nbsp; Inside your class, you simply call the delegate
(there's a recommended pattern for this as well).&amp;nbsp; But wait, there's more than
1 subscriber!&amp;nbsp; Remember, delegates aren't just function pointers, and they are
more powerful than using interfaces alone.&amp;nbsp; If you'll recall in the last post,
I said that when you create a delegate, you're really getting a MulticastDelegate,
which tracks an invocation list of delegates to run. (this is why the standard event
pattern returns void, otherwise, you've got the weird situation of multiple&amp;nbsp;return
values from what appears to be a single call).&amp;nbsp; Under normal circumstances, each
delegate in the invocation list is called and execution resumes.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=d65c3e37-70d3-4219-b8b7-34a8423f35e4" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,d65c3e37-70d3-4219-b8b7-34a8423f35e4.aspx</comments>
      <category>CLR</category>
      <category>Delegates</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=4269ecd2-381c-4ab0-ae2e-7e88ed706977</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,4269ecd2-381c-4ab0-ae2e-7e88ed706977.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,4269ecd2-381c-4ab0-ae2e-7e88ed706977.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=4269ecd2-381c-4ab0-ae2e-7e88ed706977</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Soon, my ownership area will extend to include delegates.  Since I'm fairly excited
about this, I thought I'd celebrate by writing a little something about them. 
So, what are delegates?  A casual observer might be tempted to write off delegates
as a sort of managed function pointer.  While this comparison is certainly
accurate, there's much more to explaining the power of delegates.
</p>
        <p>
In general, delegates are a sort of universal method dispatch mechanism.  Initially,
the scenario they supported was callbacks.  Delegates are one of the things that
distinguish the CLR from other VMs like Java.  Java requires the use of interfaces
to implement callbacks. (I'm only calling that out as a distinction, not saying the
Java way is bad. although personally I like what delegates bring to the table) 
So, delegates let you wrap up a method as an object to pass around, with the expectation
that it will be called from another context.
</p>
        <p>
Its sort of hard to talk about delegates because the discussion is often framed by
the language that's exposing them.  Currently, no managed language exposes them
in the way that they are represented in IL.  In C# and VB, you declare a delegate
by simply defining a method signature.  From an IL perspective, the compilers
generate a class that inherits from MulticastDelegate (another story I'll get to later),
with an Invoke method that matches your signature, and some various constructors to
support different things.  (You also usually get the corresponding asynchronous
calling pattern support methods, but I don't want to get into that)  Some other
delegate-related compiler trickery is involved in declaring events, which I'll cover
later.
</p>
        <p>
Under the covers, a delegate [conceptually] contains 2 things:
</p>
        <ul>
          <li>
A target object 
</li>
          <li>
A target method</li>
        </ul>
        <p>
Now, generally speaking, the target method is the method to be run, and the target
object is the object on which the target method will be run, but there are cases where
this line is blurred a bit.  For instance, when a delegate is pointing to a static
method, the target object is conceptually null (internally it's not, but that's an
implementation detail).  I'll get into the other cases later.
</p>
        <p>
So now you're saying, "Yup, that's a delegate.  Big deal.  What's so cool
about that?"  What's cool about that, my friend is that delegates are the things
that power virtually all of the coolest new language features that came out in v2.0
and will be coming out, including all the dynamic language goodness like IronPython. 
It's the dynamic stuff that is really exciting, so let's talk about how delegates
enable dynamic languages on top of a statically typed system.
</p>
        <p>
(To be fair, Jim Hugunin did his initial Iron Python work before these features were
available, but they now play a big role)  One of the pieces of work done in v2.0
was called delegate relaxation.  Previously, the target method had to match the
delegate signature exactly.  Now, as you might expect intuitively, the signature
can be relaxed such that the target method can have "more general" parameters and
return something "more specific" than the delegate's signature.  This is typically
defined in terms of covariance and contravariance, terms that even people who understand
them get confused.  Here's the way I usually remember it: If I could wrap the
target method with a method having the delegate's signature without casting, it will
work. Anyway, this feature makes delegates quite a bit more flexible.
</p>
        <p>
Before I go into the other features, lets talk a little about implementation. In normal
method calling in the CLR, the first parameter becomes the "this" object.  (Which
is why you see ldarg.0 in IL to put it on the stack.)  So, conceptually, the
target object represents the first argument for the method. (There is an implementation
detail that allows static methods to be called using the same convention, which is
a really elegant solution) So, by extending this idea of the target object simply
being the first argument, we get a couple of interesting variants.
</p>
        <p>
The first is what is called "closed" static delegates.  This allows you
to specify the first argument of a static method at delegate creation rather
than at the callsite.  Notice this maps quite nicely to the dynamic language
concept of adding a method to an existing instance of an object.  The language
runtime just needs to be able to track these extra methods as part of its method dispatch
logic.
</p>
        <p>
The second feature is "open" instance delegates.  This allows you to create a
delegate that points to an instance method, but doesn't define the target object. 
Instead, the delegate signature can have an extra first argument that will specify
the target object at the callsite.  When used with LCG (DynamicMethod), this
can be used to implement things like adding a method to an existing type.  Again,
the language runtime merely needs to add the logic to method dispatch.
</p>
        <p>
These 2 features are intriguing to me because they are not directly exposed from VB
or C#.  I believe VB9 exposes these, but they are not accessible in an early
bound way in C#.  You can, however, create them via <a href="http://www.marklio.com/marklio/ct.ashx?id=4269ecd2-381c-4ab0-ae2e-7e88ed706977&amp;url=http%3a%2f%2fmsdn2.microsoft.com%2fen-us%2flibrary%2fsystem.delegate.createdelegate.aspx" target="_blank">Delegate.CreateDelegate()</a> using
reflection, or use Reflection.Emit to generate the corresponding IL.
</p>
        <p>
Hopefully, I'll have some time in the future to do some samples of these as well as
discuss more about how these improve the dynamic language support in the CLR.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=4269ecd2-381c-4ab0-ae2e-7e88ed706977" />
      </body>
      <title>Delegates in the CLR</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,4269ecd2-381c-4ab0-ae2e-7e88ed706977.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,4269ecd2-381c-4ab0-ae2e-7e88ed706977.aspx</link>
      <pubDate>Thu, 15 Feb 2007 22:32:53 GMT</pubDate>
      <description>&lt;p&gt;
Soon, my ownership area will extend to include delegates.&amp;nbsp; Since I'm fairly excited
about this, I thought I'd celebrate by writing a little something about them.&amp;nbsp;
So, what are delegates?&amp;nbsp; A casual observer might be tempted to write off delegates
as a sort of&amp;nbsp;managed function pointer.&amp;nbsp; While this comparison is certainly
accurate, there's much more to explaining the power of delegates.
&lt;/p&gt;
&lt;p&gt;
In general, delegates are a sort of universal method dispatch mechanism.&amp;nbsp; Initially,
the scenario they supported was callbacks.&amp;nbsp; Delegates are one of the things that
distinguish the CLR from other VMs like Java.&amp;nbsp; Java requires the use of interfaces
to implement callbacks. (I'm only calling that out as a distinction, not saying the
Java way is bad. although personally I like what delegates bring to the table)&amp;nbsp;
So, delegates let you wrap up a method as an object to pass around, with the expectation
that it will be called from another context.
&lt;/p&gt;
&lt;p&gt;
Its sort of hard to talk about delegates because the discussion is often framed by
the language that's exposing them.&amp;nbsp; Currently, no managed language exposes them
in the way that they are represented in IL.&amp;nbsp; In C# and VB, you declare a delegate
by simply defining a method signature.&amp;nbsp; From an IL perspective, the compilers
generate a class that inherits from MulticastDelegate (another story I'll get to later),
with an Invoke method that matches your signature, and some various constructors to
support different things.&amp;nbsp; (You also usually&amp;nbsp;get the corresponding asynchronous
calling pattern support methods, but I don't want to get into that)&amp;nbsp; Some other
delegate-related compiler trickery is involved in declaring events, which I'll cover
later.
&lt;/p&gt;
&lt;p&gt;
Under the covers, a delegate [conceptually] contains 2 things:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
A target object 
&lt;li&gt;
A target method&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Now, generally speaking, the target method is the method to be run, and the target
object is the object on which the target method will be run, but there are cases where
this line is blurred a bit.&amp;nbsp; For instance, when a delegate is pointing to a static
method, the target object is conceptually null (internally it's not, but that's an
implementation detail).&amp;nbsp; I'll get into the other cases later.
&lt;/p&gt;
&lt;p&gt;
So now you're saying, "Yup, that's a delegate.&amp;nbsp; Big deal.&amp;nbsp; What's so cool
about that?"&amp;nbsp; What's cool about that, my friend is that delegates are the things
that power virtually all of the coolest new language features that came out in v2.0
and will be coming out, including all the dynamic language goodness like IronPython.&amp;nbsp;
It's the dynamic stuff that is really exciting, so let's talk about how delegates
enable dynamic languages on top of a statically typed system.
&lt;/p&gt;
&lt;p&gt;
(To be fair, Jim Hugunin did his initial Iron Python work before these features were
available, but they now play a big role)&amp;nbsp; One of the pieces of work done in v2.0
was called delegate relaxation.&amp;nbsp; Previously, the target method had to match the
delegate signature exactly.&amp;nbsp; Now, as you might expect intuitively, the signature
can be relaxed such that the target method can have "more general" parameters and
return something "more specific" than the delegate's signature.&amp;nbsp; This is typically
defined in terms of covariance and contravariance, terms that even people who understand
them get confused.&amp;nbsp; Here's the way I usually remember it: If I could wrap the
target method with a method having the delegate's signature without casting, it will
work. Anyway, this feature makes delegates quite a bit more flexible.
&lt;/p&gt;
&lt;p&gt;
Before I go into the other features, lets talk a little about implementation. In normal
method calling in the CLR, the first parameter becomes the "this" object.&amp;nbsp; (Which
is why you see ldarg.0 in IL to put it on the stack.)&amp;nbsp; So, conceptually, the
target object represents the first argument for the method. (There is an implementation
detail that allows static methods to be called using the same convention, which is
a really elegant solution) So, by extending this idea of the target object simply
being the first argument, we get a couple of interesting variants.
&lt;/p&gt;
&lt;p&gt;
The first is what is called "closed" static delegates.&amp;nbsp;&amp;nbsp;This allows you
to specify the first argument&amp;nbsp;of a static method at delegate creation rather
than at the callsite.&amp;nbsp; Notice this maps quite nicely to the dynamic language
concept of adding a method to an existing instance of an object.&amp;nbsp; The language
runtime just needs to be able to track these extra methods as part of its method dispatch
logic.
&lt;/p&gt;
&lt;p&gt;
The second feature is "open" instance delegates.&amp;nbsp; This allows you to create a
delegate that points to an instance method, but doesn't define the target object.&amp;nbsp;
Instead, the delegate signature can have an extra first argument that will specify
the target object at the callsite.&amp;nbsp; When used with LCG (DynamicMethod), this
can be used to implement things like adding a method to an existing type.&amp;nbsp; Again,
the language runtime merely needs to add the logic to method dispatch.
&lt;/p&gt;
&lt;p&gt;
These 2 features are intriguing to me because they are not directly exposed from VB
or C#.&amp;nbsp; I believe VB9 exposes these, but they are not accessible in an early
bound way in C#.&amp;nbsp; You can, however,&amp;nbsp;create them via &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=4269ecd2-381c-4ab0-ae2e-7e88ed706977&amp;amp;url=http%3a%2f%2fmsdn2.microsoft.com%2fen-us%2flibrary%2fsystem.delegate.createdelegate.aspx" target=_blank&gt;Delegate.CreateDelegate()&lt;/a&gt; using
reflection, or use Reflection.Emit to generate the corresponding IL.
&lt;/p&gt;
&lt;p&gt;
Hopefully, I'll have some time in the future to do some samples of these as well as
discuss more about how these improve the dynamic language support in the CLR.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=4269ecd2-381c-4ab0-ae2e-7e88ed706977" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,4269ecd2-381c-4ab0-ae2e-7e88ed706977.aspx</comments>
      <category>CLR</category>
      <category>Delegates</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=077f85a7-d422-403d-8e12-3752fc037dd3</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,077f85a7-d422-403d-8e12-3752fc037dd3.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,077f85a7-d422-403d-8e12-3752fc037dd3.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=077f85a7-d422-403d-8e12-3752fc037dd3</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I dealt with several situations in the past months where the crux of the problem was
confusion over assemblyname and filename.  Let's define what we're talking about:
</p>
        <ul>
          <li>
Filename - The name of a file in the filesystem, such as System.dll</li>
          <li>
Assemblyname - The name given to an assembly to establish its identity.  In this
case, we'll only concern ourselves with the "simple" name. such as System</li>
        </ul>
        <p>
Usually, any confusion that arises between the two can be resolved by reminding people
that a filesystem is just one of the places you can get an assembly from.  For
instance there are APIs for getting assemblies from byte arrays.
</p>
        <p>
For those that still do see it... In the managed world, the assemblyname gives identity
to the code that resides in the assembly.  If you have 2 assemblies with the
same assemblyname, you expect them to represent the same identity (perhaps different
versions, build flavors, bitness, etc.).  If we relied on the filesystem name,
the identity of the code could change just by changing the filename.  That's
not the semantics we expect.
</p>
        <p>
So, why does the filename matter?  Why do we recommend keeping them the same? 
Some of the reasons are simple convenience.  It's nice to look at a file and
know what it is without cracking it open.  If the names are different, it's like
me going to a party and wearing a nametag that says, "Peter".  While there is
nothing keeping me from doing it, it causes confusion.  However, another more
important reason to keep them the same is that assemblies are rarely loaded by filename. 
References and most dynamic loads are done by assemblyname.  You don't take a
reference to System.dll, you take a reference to System.  At some point, the
loader has to find an appropriate file to load to satisfy that reference.  If
System's filename is Peter.dll, then it's going to have a difficult time finding it
to load.  This is actually the very reason that gacutil will not let you install
an assembly into the global assembly cache if the filename doesn't match the assemblyname. 
However, I think it's silly that it doesn't just fix the name for you.
</p>
        <p>
What about multi-module assemblies?  Well, it's the module with the assembly
manifest that matters.  It's the one that should match.  Then the rest of
the files need to match the assembly manifest :). But, if you're using multi-module
assemblies, let me know.  I'd like to know why.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=077f85a7-d422-403d-8e12-3752fc037dd3" />
      </body>
      <title>Assemblyname vs. Filename</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,077f85a7-d422-403d-8e12-3752fc037dd3.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,077f85a7-d422-403d-8e12-3752fc037dd3.aspx</link>
      <pubDate>Mon, 29 Jan 2007 20:46:56 GMT</pubDate>
      <description>&lt;p&gt;
I dealt with several situations in the past months where the crux of the problem was
confusion over assemblyname and filename.&amp;nbsp; Let's define what we're talking about:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Filename - The name of a file in the filesystem, such as System.dll&lt;/li&gt;
&lt;li&gt;
Assemblyname - The name given to an assembly to establish its identity.&amp;nbsp; In this
case, we'll only concern ourselves with the "simple" name.&amp;nbsp;such as System&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Usually, any confusion that arises between the two can be resolved by reminding people
that a filesystem is just one of the places you can get an assembly from.&amp;nbsp; For
instance there are APIs for getting assemblies from byte arrays.
&lt;/p&gt;
&lt;p&gt;
For those that still do see it... In the managed world, the assemblyname gives identity
to the code that resides in the assembly.&amp;nbsp; If you have 2 assemblies with the
same assemblyname, you expect them to represent the same identity (perhaps different
versions, build flavors, bitness, etc.).&amp;nbsp; If we relied on the filesystem name,
the identity of the code could change just by changing the filename.&amp;nbsp; That's
not the semantics we expect.
&lt;/p&gt;
&lt;p&gt;
So, why does the filename matter?&amp;nbsp; Why do we recommend keeping them the same?&amp;nbsp;
Some of the reasons are simple convenience.&amp;nbsp; It's nice to look at a file and
know what it is without cracking it open.&amp;nbsp; If the names are different, it's like
me going to a party and wearing a nametag that says, "Peter".&amp;nbsp; While there is
nothing keeping me from doing it, it causes confusion.&amp;nbsp; However, another more
important reason to keep them the same is that assemblies are rarely loaded by filename.&amp;nbsp;
References and most dynamic loads are done by assemblyname.&amp;nbsp; You don't take a
reference to System.dll, you take a reference to System.&amp;nbsp; At some point, the
loader has to find an appropriate file to load to satisfy that reference.&amp;nbsp; If
System's filename is Peter.dll, then it's going to have a difficult time finding it
to load.&amp;nbsp; This is actually the very reason that gacutil will not let you install
an assembly into the global assembly cache if the filename doesn't match the assemblyname.&amp;nbsp;
However, I think it's silly that it doesn't just fix the name for you.
&lt;/p&gt;
&lt;p&gt;
What about multi-module assemblies?&amp;nbsp; Well, it's the module with the assembly
manifest that matters.&amp;nbsp; It's the one that should match.&amp;nbsp; Then the rest of
the files need to match the assembly manifest :).&amp;nbsp;But, if you're using multi-module
assemblies, let me know.&amp;nbsp; I'd like to know why.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=077f85a7-d422-403d-8e12-3752fc037dd3" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,077f85a7-d422-403d-8e12-3752fc037dd3.aspx</comments>
      <category>CLR</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=6ffb977d-6496-47c5-abad-4e0705bf3b0b</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,6ffb977d-6496-47c5-abad-4e0705bf3b0b.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,6ffb977d-6496-47c5-abad-4e0705bf3b0b.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=6ffb977d-6496-47c5-abad-4e0705bf3b0b</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I've mentioned before that one of my ownership areas at MS is the CLR "shim". 
Most people I've said that to ask me, "What's that?".  I usually reply that generally,
it's mscoree.dll, to which they typically respond, "Oh yeah.  What does that
do?"  In general terms, the shim is in charge of firing up the runtime in a process. 
In addition, it exposes all the hosting APIs and other stuff you need to do stuff
with the CLR from unmanaged code. If you look at a managed app, you will see that
it has a dependency on mscoree.dll, and nothing else CLR-related.  Ater the runtime
is spun up, most of the things that mscoree exposes are simply forwarded calls into
the mscorwks.dll of the runtime you have installed.
</p>
        <p>
What's interesting about mscoree.dll, is that it is the only piece of the runtime
that doesn't run side by side.  You can have v1.1 and v2.0 installed on the machine,
but you will only have one mscoree.dll.  You always have the version of mscoree.dll
that corresponds to the latest version of the runtime installed on your machine (unless
you have installed a patch or something that services mscoree, in which case you may
have a v2.0 shim even though only v1.1 is installed on your machine).
</p>
        <p>
So, naturally, backwards compatibility is extremely important in the Shim.  When
you start up managed code, the Shim decides which version of the CLR to fire up based
on lots of different things.  These things are all fairly well documented and
all have a specific scenario they enable, but by their nature they are very confusing.
</p>
        <blockquote>
          <p>
Aside: When I was job hunting, I interviewed at several companies other than Microsoft. 
During some of those other interviews, I was asked questions about what runtime would
be started under certain conditions. The rules are so confusing, that some of the
interviewers, although all extremely smart people, had formed incorrect models
of what the rules were.  Some told me I had the wrong answer to their question,
when if fact it was correct. (that's not to say that I knew the correct answers to
all of them.)
</p>
        </blockquote>
        <p>
I'm not certain that I can clear up the confusion, but I do hope to have a series
of posts in the coming months on why the shim does what it does under certain circumstances. 
Then, at least you might understand what's going on when it happens.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=6ffb977d-6496-47c5-abad-4e0705bf3b0b" />
      </body>
      <title>What is the shim?</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,6ffb977d-6496-47c5-abad-4e0705bf3b0b.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,6ffb977d-6496-47c5-abad-4e0705bf3b0b.aspx</link>
      <pubDate>Mon, 22 Jan 2007 18:50:36 GMT</pubDate>
      <description>&lt;p&gt;
I've mentioned before that one of my ownership areas at MS is the CLR "shim".&amp;nbsp;
Most people I've said that to ask me, "What's that?".&amp;nbsp; I usually reply that generally,
it's mscoree.dll, to which they typically respond, "Oh yeah.&amp;nbsp; What does that
do?"&amp;nbsp; In general terms, the shim is in charge of firing up the runtime in a process.&amp;nbsp;
In addition, it exposes all the hosting APIs and other stuff you need to do stuff
with the CLR from unmanaged code. If you look at a managed app, you will see that
it has a dependency on mscoree.dll, and nothing else CLR-related.&amp;nbsp; Ater the runtime
is spun up, most of the things that mscoree exposes are simply forwarded calls into
the mscorwks.dll of the runtime you have installed.
&lt;/p&gt;
&lt;p&gt;
What's interesting about mscoree.dll, is that it is the only piece of the runtime
that doesn't run side by side.&amp;nbsp; You can have v1.1 and v2.0 installed on the machine,
but you will only have one mscoree.dll.&amp;nbsp; You always have the version of mscoree.dll
that corresponds to the latest version of the runtime installed on your machine (unless
you have installed a patch or something that services mscoree, in which case you may
have a v2.0 shim even though only v1.1 is installed on your machine).
&lt;/p&gt;
&lt;p&gt;
So, naturally, backwards compatibility is extremely important in the Shim.&amp;nbsp; When
you start up managed code, the Shim decides which version of the CLR to fire up based
on lots of different things.&amp;nbsp; These things are all fairly well documented and
all have a specific scenario they enable, but by their nature they are very confusing.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Aside: When I was job hunting, I interviewed at several companies other than Microsoft.&amp;nbsp;
During some of those other interviews, I was asked questions about what runtime would
be started under certain conditions. The rules are so confusing, that some of the
interviewers, although all extremely smart people,&amp;nbsp;had formed incorrect models
of what the rules were.&amp;nbsp; Some told me I had the wrong answer to their question,
when if fact it was correct. (that's not to say that I knew the correct answers to
all of them.)
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
I'm not certain that I can clear up the confusion, but I do hope to have a series
of posts in the coming months on why the shim does what it does under certain circumstances.&amp;nbsp;
Then, at least you might understand what's going on when it happens.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=6ffb977d-6496-47c5-abad-4e0705bf3b0b" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,6ffb977d-6496-47c5-abad-4e0705bf3b0b.aspx</comments>
      <category>CLR</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=fcda68c3-f9de-4038-8231-917a394990a6</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,fcda68c3-f9de-4038-8231-917a394990a6.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,fcda68c3-f9de-4038-8231-917a394990a6.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=fcda68c3-f9de-4038-8231-917a394990a6</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Someone asked me the other day if you could reflect on other people's assemblies using
the CLR.  My answer was, "ABSOLUTELY!!!!!"
</p>
        <p>
As it turns out, they were having some problems achieving this, and they were wondering
if there was some kind of security mechanism in place that was preventing reflection
on 3rd party assemblies.  Here's the basic scenario.  They had a 3rd party
library with a type that defined several "constants" using fields.  They needed
to be able to specify a named constant via a string and return the value for the constant. 
Security and performance arguments aside (they had already been considered), they
simply wanted to lookup the field by name via reflection and get its value. 
This can be accomplished via just a few fairly reasonable lines of code using one
of the GetField family of methods on System.Type and then getting the value. 
I'll leave this as an exercise for the reader so they can have the fun of wresting
with the <a href="http://www.marklio.com/marklio/ct.ashx?id=fcda68c3-f9de-4038-8231-917a394990a6&amp;url=http%3a%2f%2fblogs.msdn.com%2fbrada%2farchive%2f2005%2f11%2f09%2f475090.aspx" target="_blank">silly
BindingFlags enum</a>.
</p>
        <p>
After some discussion, I learned that the trouble actually revolved around getting
the Type object in the first place.  They were using Type.GetType to load the
type with a namespace-qualified name as the string argument.  It was returning
null (Nothing in VB).  They were validating that the string was correct using
Intellisense, and concluding that since Intellisense could see the type, that Type.GetType
should also "see" it (which seems like a perfectly reasonable assumption).
</p>
        <p>
Type.GetType() takes a string argument specifying the type to retrieve.  When
specifying types in strings, you can usually use a namespace qualified name ("[namespace.]type"),
or an assembly-qualified name ("[namespace.]type, assemblyName").  If you don't
provide the assembly name, the API looks through the assemblies already loaded in
the AppDomain for a type that matches the name.  If an assembly name <strong>is</strong> specified,
a bind occurs to the assembly and it is loaded if necessary.
</p>
        <p>
In this case, there was a reference to the assembly containing the type, so Intellisense
was picking it up and providing completion. The trouble was that, at runtime, the
assembly had not yet been loaded into the AppDomain, so the type was unavailable.
</p>
        <p>
So, the options were (in order of appropriateness in my opinion):
</p>
        <ul>
          <li>
Use an early-bound type - Since the type was known at compile-time, use typeof() (GetType()
in VB).  This will create a compile-time, assembly-qualified type reference in
the IL rather than a runtime parsing/bind/load of the type string.</li>
          <li>
Use an assembly-qualified type string - Adding the assembly name to the type string
will let the CLR know what assembly to look in (and load if necessary).  There
are some subtle versioning issues with this approach, especially for strongly-named
assemblies.</li>
          <li>
Make sure the assembly is loaded prior to calling Type.GetType() - Making an early-bound call
to something else in the assembly first will get it loaded into the AppDomain. 
This seems like a fragile solution and I would not recommend it, although it will
technically work.</li>
        </ul>
        <p>
The real issue here is the number of samples (especially in VB) provided by MS that
use Type.GetType() with a non-qualified name (ex. "System.String").
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=fcda68c3-f9de-4038-8231-917a394990a6" />
      </body>
      <title>When attempting to reflect on assemblies, make sure you have the assembly loaded</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,fcda68c3-f9de-4038-8231-917a394990a6.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,fcda68c3-f9de-4038-8231-917a394990a6.aspx</link>
      <pubDate>Wed, 03 Jan 2007 17:09:25 GMT</pubDate>
      <description>&lt;p&gt;
Someone asked me the other day if you could reflect on other people's assemblies using
the CLR.&amp;nbsp; My answer was, "ABSOLUTELY!!!!!"
&lt;/p&gt;
&lt;p&gt;
As it turns out, they were having some problems achieving this, and they were wondering
if there was some kind of security mechanism in place that was preventing reflection
on 3rd party assemblies.&amp;nbsp; Here's the basic scenario.&amp;nbsp; They had a 3rd party
library with a type that defined several "constants" using fields.&amp;nbsp; They needed
to be able to specify a named constant via a string and return the value for the constant.&amp;nbsp;
Security and performance arguments aside (they had already been considered), they
simply wanted to lookup the field by name via reflection and get its value.&amp;nbsp;
This can be accomplished via just a few fairly reasonable lines of code using one
of the GetField family of methods on System.Type and then getting the value.&amp;nbsp;
I'll leave this as an exercise for the reader so they can have the fun of wresting
with the &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=fcda68c3-f9de-4038-8231-917a394990a6&amp;amp;url=http%3a%2f%2fblogs.msdn.com%2fbrada%2farchive%2f2005%2f11%2f09%2f475090.aspx" target="_blank"&gt;silly
BindingFlags enum&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
After some discussion, I learned that the trouble actually revolved around getting
the Type object in the first place.&amp;nbsp; They were using Type.GetType to load the
type with a namespace-qualified name as the string argument.&amp;nbsp; It was returning
null (Nothing in VB).&amp;nbsp; They were validating that the string was correct using
Intellisense, and concluding that since Intellisense could see the type, that Type.GetType
should also "see" it (which seems like a perfectly reasonable assumption).
&lt;/p&gt;
&lt;p&gt;
Type.GetType() takes a string argument specifying the type to retrieve.&amp;nbsp; When
specifying types in strings, you can usually use a namespace qualified name ("[namespace.]type"),
or an assembly-qualified name ("[namespace.]type, assemblyName").&amp;nbsp; If you don't
provide the assembly name, the API looks through the assemblies already loaded in
the AppDomain for a type that matches the name.&amp;nbsp; If an assembly name &lt;strong&gt;is&lt;/strong&gt; specified,
a bind occurs to the assembly and it is loaded if necessary.
&lt;/p&gt;
&lt;p&gt;
In this case, there was a reference to the assembly containing the type, so Intellisense
was picking it up and providing completion. The trouble was that, at runtime, the
assembly had not yet been loaded into the AppDomain, so the type was unavailable.
&lt;/p&gt;
&lt;p&gt;
So, the options were (in order of appropriateness in my opinion):
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Use an early-bound type - Since the type was known at compile-time, use typeof() (GetType()
in VB).&amp;nbsp; This will create a compile-time, assembly-qualified type reference in
the IL rather than a runtime parsing/bind/load of the type string.&lt;/li&gt;
&lt;li&gt;
Use an assembly-qualified type string - Adding the assembly name to the type string
will let the CLR know what assembly to look in (and load if necessary).&amp;nbsp; There
are some subtle versioning issues with this approach, especially for strongly-named
assemblies.&lt;/li&gt;
&lt;li&gt;
Make sure the assembly is loaded prior to calling Type.GetType() - Making an early-bound&amp;nbsp;call
to something else in the assembly first will get it loaded into the AppDomain.&amp;nbsp;
This seems like a fragile solution and I would not recommend it, although it will
technically work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
The real issue here is the number of samples (especially in VB) provided by MS that
use Type.GetType() with a non-qualified name (ex. "System.String").
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=fcda68c3-f9de-4038-8231-917a394990a6" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,fcda68c3-f9de-4038-8231-917a394990a6.aspx</comments>
      <category>CLR</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=e236f878-8b57-4c03-a3ba-d4b5a9d3147e</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,e236f878-8b57-4c03-a3ba-d4b5a9d3147e.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,e236f878-8b57-4c03-a3ba-d4b5a9d3147e.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=e236f878-8b57-4c03-a3ba-d4b5a9d3147e</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Historically, when I gotten questions from friends and colleagues regarding performance,
I've often sent them straight to <a href="http://www.marklio.com/marklio/ct.ashx?id=e236f878-8b57-4c03-a3ba-d4b5a9d3147e&amp;url=http%3a%2f%2fblogs.msdn.com%2fricom%2fdefault.aspx" target="_blank">Rico
Mariani's blog</a>.  It is a wonderful source of advice, guidance, rules and
humor in the realm of performance.  His <a href="http://www.marklio.com/marklio/ct.ashx?id=e236f878-8b57-4c03-a3ba-d4b5a9d3147e&amp;url=http%3a%2f%2fblogs.msdn.com%2fricom%2farchive%2f2006%2f11%2f15%2fcosts-and-modelling.aspx" target="_blank">latest
entry</a> is another wonderful piece.
</p>
        <p>
I've spoken with several individuals who have said things like, "Well, our goal was
to be able to handle a request in X seconds, or handle Y amount of throughput, and
we're too slow.  Any ideas?"  More than likely, they've done their design
and implementation without any work to make sure they reach their performance
goals, and by that time, my advice to "get rid of that dependency", or "redesign
this component" is too late.  When factoring the performance goals into those
design decisions would have raised the red flag immediately. 
</p>
        <p>
I love his approaches because they tend to sound alot more like engineering (which
is my background) than alot of guidance that tends to be thrown around.  Here's
my favorite quote:
</p>
        <blockquote>
          <p>
            <font color="#808080">
              <em>I get very worried when people say things like “Productivity
and cleanliness always trump performance.”   Productivity is about creating
product.  A “clean” design which fundamentally fails to address performance requirements
is not an example of a productive enterprise, it is a looming disaster.  A developer
productively engaged in creating a failure is uninteresting.</em>
            </font> 
</p>
        </blockquote>
        <p>
Now that Rico and I work for the same company (across the street from each other)
perhaps I can come up with a good excuse to meet him in person.
</p>
        <p>
[UPDATE] After reading this, I thought it came off a little snobbish.  I think
we've all been in the above situation.  Many times, through no fault of our own. 
We're often the victims of process, bureaucracy or other external forces that often
oppose success.  Please don't feel like I'm talking down to anyone.  Hindsight
is 20/20.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=e236f878-8b57-4c03-a3ba-d4b5a9d3147e" />
      </body>
      <title>More Gold From Rico</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,e236f878-8b57-4c03-a3ba-d4b5a9d3147e.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,e236f878-8b57-4c03-a3ba-d4b5a9d3147e.aspx</link>
      <pubDate>Wed, 15 Nov 2006 21:07:39 GMT</pubDate>
      <description>&lt;p&gt;
Historically, when I gotten questions from friends and colleagues regarding performance,
I've often sent them straight to &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=e236f878-8b57-4c03-a3ba-d4b5a9d3147e&amp;amp;url=http%3a%2f%2fblogs.msdn.com%2fricom%2fdefault.aspx" target="_blank"&gt;Rico
Mariani's blog&lt;/a&gt;.&amp;nbsp; It is a wonderful source of advice, guidance, rules and
humor in the realm of performance.&amp;nbsp; His &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=e236f878-8b57-4c03-a3ba-d4b5a9d3147e&amp;amp;url=http%3a%2f%2fblogs.msdn.com%2fricom%2farchive%2f2006%2f11%2f15%2fcosts-and-modelling.aspx" target="_blank"&gt;latest
entry&lt;/a&gt; is another wonderful piece.
&lt;/p&gt;
&lt;p&gt;
I've spoken with several individuals who have said things like, "Well, our goal was
to be able to handle a request in X seconds, or handle Y amount of throughput, and
we're too slow.&amp;nbsp; Any ideas?"&amp;nbsp; More than likely, they've done their design
and implementation without any work to&amp;nbsp;make sure they reach their performance
goals, and by that time, my advice to "get rid of that dependency", or&amp;nbsp;"redesign
this component" is too late.&amp;nbsp; When factoring the performance goals into those
design decisions&amp;nbsp;would have raised the red flag immediately.&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
I love his approaches because they tend to sound alot more like engineering (which
is my background) than alot of guidance that tends to be thrown around.&amp;nbsp; Here's
my favorite quote:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;font color="#808080"&gt;&lt;em&gt;I get very worried when people say things like “Productivity
and cleanliness always trump performance.”&amp;nbsp;&amp;nbsp; Productivity is about creating
product.&amp;nbsp; A “clean” design which fundamentally fails to address performance requirements
is not an example of a productive enterprise, it is a looming disaster.&amp;nbsp; A developer
productively engaged in creating a failure is uninteresting.&lt;/em&gt;&lt;/font&gt;&amp;nbsp;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Now that Rico and I work for the same company (across the street from each other)
perhaps I can come up with a good excuse to meet him in person.
&lt;/p&gt;
&lt;p&gt;
[UPDATE] After reading this, I thought it came off a little snobbish.&amp;nbsp; I think
we've all been in the above situation.&amp;nbsp; Many times, through no fault of our own.&amp;nbsp;
We're often the victims of process, bureaucracy or other external forces that often
oppose success.&amp;nbsp; Please don't feel like I'm talking down to anyone.&amp;nbsp; Hindsight
is 20/20.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=e236f878-8b57-4c03-a3ba-d4b5a9d3147e" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,e236f878-8b57-4c03-a3ba-d4b5a9d3147e.aspx</comments>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=4c4d6194-5bd1-4c4d-9415-acbf92b9bc1d</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,4c4d6194-5bd1-4c4d-9415-acbf92b9bc1d.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,4c4d6194-5bd1-4c4d-9415-acbf92b9bc1d.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=4c4d6194-5bd1-4c4d-9415-acbf92b9bc1d</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Something that always bothered me at my previous job was having to install the
framework SDK to get a copy of gacutil.exe.  I know the guys still there hate
having to install the SDK on a server so they can manipulate the GAC.  Richard
Lander <a href="http://www.marklio.com/marklio/ct.ashx?id=4c4d6194-5bd1-4c4d-9415-acbf92b9bc1d&amp;url=http%3a%2f%2fhoser.lander.ca%2fGACUtil%2bV20%2b%2bWhere%2bTo%2bGet%2bIt.aspx" target="_blank">gives
some interesting information</a> on the topic, but he doesn't go into <strong>why</strong> it's
not included in the redist.
</p>
        <p>
Since I've been at MS, I've learned a great deal more about the Global Assembly Cache
(GAC) and the fusion APIs. Last night, I was taking a shower after cutting my hair,
and the reason came to me.  That reason is... installers, or more importantly...
uninstallers.
</p>
        <p>
During a discussion recently, I heard an amazingly profound saying:
</p>
        <blockquote>
          <p>
"It is better to fail to do, than to fail to undo"
</p>
        </blockquote>
        <p>
I don't recall who said it, and they probably got it from someone else, but it is
right on the money.
</p>
        <p>
When programs uninstall, they have to correctly remove things they've placed in the
GAC.  Let's make up an example.  Let's say I have some software company. 
We've developed a magical managed library that makes it wicked easy to develop
our software, so we use it in all our products.  Let's say that in our deployment
model, it makes sense to deploy that library to the GAC.  So, uninstalling our
software should remove it from the GAC, right?  We'll what if one of our other
products is on the machine? We don't want to uninstall one and break the remaining
one.
</p>
        <p>
When you install an assembly into the GAC via the Fusion APIs, you do so with a traced
reference.  That reference tells Fusion "who" installed it.  If 2 installers
install the same assembly, it's smart enough to know not to remove the assembly until <strong>both</strong> uninstall.
</p>
        <p>
GACUtil, as a management tool, enables you to  use traced references as
well, but it also allows you to install without a traced references.  It also
allows you to force uninstalls and do lots of other screwy things.  In other
words, the tool is too powerful.  Devs need to be able to do screwy things. 
Administrators need to be able to do screwy things.  Regular users don't. 
Give them an install package that handles everything.  Otherwise, you're bound
to have a support nightmare.
</p>
        <p>
If I have time, or enough requests, we'll go into how to use the fusion APIs directly
to manage the GAC.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=4c4d6194-5bd1-4c4d-9415-acbf92b9bc1d" />
      </body>
      <title>Why is GACUtil.exe not part of the .NET Framework?</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,4c4d6194-5bd1-4c4d-9415-acbf92b9bc1d.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,4c4d6194-5bd1-4c4d-9415-acbf92b9bc1d.aspx</link>
      <pubDate>Tue, 14 Nov 2006 17:10:30 GMT</pubDate>
      <description>&lt;p&gt;
Something that always bothered me at my previous job&amp;nbsp;was having to install the
framework SDK to get a copy of gacutil.exe.&amp;nbsp; I know the guys still there hate
having to install the SDK on a server so they can manipulate the GAC.&amp;nbsp; Richard
Lander &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=4c4d6194-5bd1-4c4d-9415-acbf92b9bc1d&amp;amp;url=http%3a%2f%2fhoser.lander.ca%2fGACUtil%2bV20%2b%2bWhere%2bTo%2bGet%2bIt.aspx" target="_blank"&gt;gives
some&amp;nbsp;interesting information&lt;/a&gt;&amp;nbsp;on the topic, but he doesn't go into &lt;strong&gt;why&lt;/strong&gt; it's
not included in the redist.
&lt;/p&gt;
&lt;p&gt;
Since I've been at MS, I've learned a great deal more about the Global Assembly Cache
(GAC) and the fusion APIs. Last night, I was taking a shower after cutting my hair,
and the reason came to me.&amp;nbsp; That reason is... installers, or more importantly...
uninstallers.
&lt;/p&gt;
&lt;p&gt;
During a discussion recently, I heard an amazingly profound saying:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
"It is better to fail to do, than to fail to undo"
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
I don't recall who said it, and they probably got it from someone else, but it is
right on the money.
&lt;/p&gt;
&lt;p&gt;
When programs uninstall, they have to correctly remove things they've placed in the
GAC.&amp;nbsp; Let's make up an example.&amp;nbsp; Let's say I have some software company.&amp;nbsp;
We've developed a magical&amp;nbsp;managed library that makes it wicked easy to develop
our software, so we use it in all our products.&amp;nbsp; Let's say that in our deployment
model, it makes sense to deploy that library to the GAC.&amp;nbsp; So, uninstalling our
software should remove it from the GAC, right?&amp;nbsp; We'll what if one of our other
products is on the machine? We don't want to uninstall one and break the remaining
one.
&lt;/p&gt;
&lt;p&gt;
When you install an assembly into the GAC via the Fusion APIs, you do so with a traced
reference.&amp;nbsp; That&amp;nbsp;reference tells Fusion "who" installed it.&amp;nbsp; If 2 installers
install the same assembly, it's smart enough to know not to remove the assembly until &lt;strong&gt;both&lt;/strong&gt; uninstall.
&lt;/p&gt;
&lt;p&gt;
GACUtil, as a management tool, enables you to&amp;nbsp;&amp;nbsp;use traced references as
well, but it also allows you to install without a traced references.&amp;nbsp; It also
allows you to force uninstalls and do lots of other screwy things.&amp;nbsp; In other
words, the tool is too powerful.&amp;nbsp; Devs need to be able to do screwy things.&amp;nbsp;
Administrators need to be able to do screwy things.&amp;nbsp; Regular users don't.&amp;nbsp;
Give them an install package that handles everything.&amp;nbsp; Otherwise, you're bound
to have a support nightmare.
&lt;/p&gt;
&lt;p&gt;
If I have time, or enough requests, we'll go into how to use the fusion APIs directly
to manage the GAC.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=4c4d6194-5bd1-4c4d-9415-acbf92b9bc1d" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,4c4d6194-5bd1-4c4d-9415-acbf92b9bc1d.aspx</comments>
      <category>CLR</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=f721f518-fdc6-40e5-bac0-624e9b869164</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,f721f518-fdc6-40e5-bac0-624e9b869164.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,f721f518-fdc6-40e5-bac0-624e9b869164.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=f721f518-fdc6-40e5-bac0-624e9b869164</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Several people have complained that I haven't made any entries in a while.  There
are several reasons for this.  Aside from being generally busy, I'm signed up
to do some posts about the CLR in general, and some from my ownership areas as part
of my job.  This has resulted in several "half-baked" entries ranging from hosting
the runtime to the Global Assembly Cache, to some other more general CLR-related entries.
</p>
        <p>
In addition, MS has had several new products in the queue that were on the verge of
releasing, and I've had entries waiting for them to release.  Of course, being
on the safe side, I've waited for someone else to blog first, at which point an extra
post from me doesn't make much difference.
</p>
        <p>
And thirdly, Jenna is growing like a weed and it's hard to find time to sit down and
formulate posts when you're chasing her around the house.
</p>
        <p>
So, regarding technical content.  I'd like to get an idea of what people are
interested in hearing about. So shoot me an email or leave a comment with suggestions
for posts regarding the CLR in general or specifically within my areas of ownership:
</p>
        <ul>
          <li>
The unmanaged hosting API's (CorBindToRuntime, etc.). These are what you'd use
to host the CLR in your own app in order to more tightly control things, or provide
additional isolation or escalation policies. 
</li>
          <li>
The global assembly cache 
</li>
          <li>
"automatic" CLR activation - what I mean by this is what happens when the runtime
is spun up my a managed app, or via COM interop.  Things like how to decide which
runtime to use, etc.</li>
        </ul>
        <p>
In addition, I'll try to keep the personal updates coming for those who are not looking
for just technical content.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=f721f518-fdc6-40e5-bac0-624e9b869164" />
      </body>
      <title>RFP (Requests for posts)</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,f721f518-fdc6-40e5-bac0-624e9b869164.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,f721f518-fdc6-40e5-bac0-624e9b869164.aspx</link>
      <pubDate>Mon, 13 Nov 2006 20:49:21 GMT</pubDate>
      <description>&lt;p&gt;
Several people have complained that I haven't made any entries in a while.&amp;nbsp; There
are several reasons for this.&amp;nbsp; Aside from being generally busy, I'm signed up
to do some posts about the CLR in general, and some from my ownership areas as part
of my job.&amp;nbsp; This has resulted in several "half-baked" entries ranging from hosting
the runtime to the Global Assembly Cache, to some other more general CLR-related entries.
&lt;/p&gt;
&lt;p&gt;
In addition, MS has had several new products in the queue that were on the verge of
releasing, and I've had entries waiting for them to release.&amp;nbsp; Of course, being
on the safe side, I've waited for someone else to blog first, at which point an extra
post from me doesn't make much difference.
&lt;/p&gt;
&lt;p&gt;
And thirdly, Jenna is growing like a weed and it's hard to find time to sit down and
formulate posts when you're chasing her around the house.
&lt;/p&gt;
&lt;p&gt;
So, regarding technical content.&amp;nbsp; I'd like to get an idea of what people are
interested in hearing about.&amp;nbsp;So shoot me an email or leave a comment with suggestions
for posts regarding the CLR in general or&amp;nbsp;specifically within my areas of ownership:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
The unmanaged hosting API's (CorBindToRuntime, etc.).&amp;nbsp;These are what you'd use
to host the CLR in your own app in order to more tightly control things, or provide
additional isolation or escalation policies. 
&lt;li&gt;
The global assembly cache 
&lt;li&gt;
"automatic" CLR activation - what I mean by this is what happens when the runtime
is spun up my a managed app, or via COM interop.&amp;nbsp; Things like how to decide which
runtime to use, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
In addition, I'll try to keep the personal updates coming for those who are not looking
for just technical content.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=f721f518-fdc6-40e5-bac0-624e9b869164" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,f721f518-fdc6-40e5-bac0-624e9b869164.aspx</comments>
      <category>Technical</category>
      <category>CLR</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=ae1e534a-6f31-4420-9b7f-782b01453438</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,ae1e534a-6f31-4420-9b7f-782b01453438.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,ae1e534a-6f31-4420-9b7f-782b01453438.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=ae1e534a-6f31-4420-9b7f-782b01453438</wfw:commentRss>
      <slash:comments>6</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
For some reason, it really bothers me when I see this pattern in code (using no particular
language):
</p>
        <code> someVar = false;<br />
if (someCondition) {<br />
someVar = true;<br />
}<br /></code>
        <p>
This can, of course, simply be specified as:
</p>
        <code> someVar = someCondition; </code>
        <p>
Now, I understand that as code is refactored, this pattern can appear due to simplifications...but
still...come on. It's even worse when someVar is used only as the condition of another
if block.
</p>
        <p>
UPDATE: This seems to occur most often in code whose ownership has changed hands several
times. New owners seem to fall into either trying to edit the code while maintaining
the structure as closely as possible, or by heavily refactoring. Many times, the former
choice is made, especially if the original owner is still around somewhere. Usually
my first instinct when I inherit code is to massively refactor. I'll post a more in-depth
view on this later.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=ae1e534a-6f31-4420-9b7f-782b01453438" />
      </body>
      <title>Silly Code</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,ae1e534a-6f31-4420-9b7f-782b01453438.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,ae1e534a-6f31-4420-9b7f-782b01453438.aspx</link>
      <pubDate>Tue, 12 Sep 2006 22:09:58 GMT</pubDate>
      <description>&lt;p&gt;
For some reason, it really bothers me when I see this pattern in code (using no particular
language):
&lt;/p&gt;
&lt;code&gt; someVar = false;&lt;br /&gt;
if (someCondition) {&lt;br /&gt;
someVar = true;&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt; 
&lt;p&gt;
This can, of course, simply be specified as:
&lt;/p&gt;
&lt;code&gt; someVar = someCondition; &lt;/code&gt; 
&lt;p&gt;
Now, I understand that as code is refactored, this pattern can appear due to simplifications...but
still...come on. It's even worse when someVar is used only as the condition of another
if block.
&lt;/p&gt;
&lt;p&gt;
UPDATE: This seems to occur most often in code whose ownership has changed hands several
times. New owners seem to fall into either trying to edit the code while maintaining
the structure as closely as possible, or by heavily refactoring. Many times, the former
choice is made, especially if the original owner is still around somewhere. Usually
my first instinct when I inherit code is to massively refactor. I'll post a more in-depth
view on this later.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=ae1e534a-6f31-4420-9b7f-782b01453438" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,ae1e534a-6f31-4420-9b7f-782b01453438.aspx</comments>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=f1831673-c465-4a2b-a868-723a4963792b</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,f1831673-c465-4a2b-a868-723a4963792b.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,f1831673-c465-4a2b-a868-723a4963792b.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=f1831673-c465-4a2b-a868-723a4963792b</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I thought some others might find this useful.
</p>
        <p>
I have been baffled for a few days why certain actions in an experimental Rails app
would work fine in dev mode, and then give me mysterious HTTP 500 errors when deployed. 
The Rails logs would tell me everything was just fine and there was no problem. But,
there they were in Fiddler... status 500.  I haven't figured out how to get ahold
of the Apache logs from my host yet, so they couldn't help me.
</p>
        <p>
I finally set up Apache with FastCGI myself so I could attempt to duplicate the problem. 
It was immediately apparent.  The Apache log was complaining about invalid headers
in the FastCGI communication.  I was using "puts" to write out to the console
when running in dev mode in order to quickly debug what was going on.  This works
fine when using the Webrick standalone server, but FastCGI on Apache evidently uses
stdout to do the communication between it and the fastcgi processes, and writing to
stdout screws up that communication and Apache reports HTTP 500, even though Rails
thinks everything's A-OK.
</p>
        <p>
The lovely thing about Ruby is that I was able to fix it by redefining puts to do
nothing.  Ideally, you ought to use the logging mechanisms, and I will. 
But that made a great short-term fix.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=f1831673-c465-4a2b-a868-723a4963792b" />
      </body>
      <title>Don't write to stdout in Rails</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,f1831673-c465-4a2b-a868-723a4963792b.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,f1831673-c465-4a2b-a868-723a4963792b.aspx</link>
      <pubDate>Tue, 23 May 2006 19:59:36 GMT</pubDate>
      <description>&lt;p&gt;
I thought some others might find this useful.
&lt;/p&gt;
&lt;p&gt;
I have been baffled for a few days why certain actions in an experimental Rails app
would work fine in dev mode, and then give me mysterious HTTP 500 errors when deployed.&amp;nbsp;
The Rails logs would tell me everything was just fine and there was no problem. But,
there they were in Fiddler... status 500.&amp;nbsp; I haven't figured out how to get ahold
of the Apache logs from my host yet, so they couldn't help me.
&lt;/p&gt;
&lt;p&gt;
I finally set up Apache with FastCGI myself so I could attempt to duplicate the problem.&amp;nbsp;
It was immediately apparent.&amp;nbsp; The Apache log was complaining about invalid headers
in the FastCGI communication.&amp;nbsp; I was using "puts" to write out to the console
when running in dev mode in order to quickly debug what was going on.&amp;nbsp; This works
fine when using the Webrick standalone server, but FastCGI on Apache evidently uses
stdout to do the communication between it and the fastcgi processes, and writing to
stdout screws up that communication and Apache reports HTTP 500, even though Rails
thinks everything's A-OK.
&lt;/p&gt;
&lt;p&gt;
The lovely thing about Ruby is that I was able to fix it by redefining puts to do
nothing.&amp;nbsp; Ideally, you ought to use the logging mechanisms, and I will.&amp;nbsp;
But that made a great short-term fix.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=f1831673-c465-4a2b-a868-723a4963792b" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,f1831673-c465-4a2b-a868-723a4963792b.aspx</comments>
      <category>Crazy stuff</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=bdcef32a-18ba-4dd3-8f99-3d8e2c569e47</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,bdcef32a-18ba-4dd3-8f99-3d8e2c569e47.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,bdcef32a-18ba-4dd3-8f99-3d8e2c569e47.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=bdcef32a-18ba-4dd3-8f99-3d8e2c569e47</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
During the last PDC, <a href="http://www.marklio.com/marklio/ct.ashx?id=bdcef32a-18ba-4dd3-8f99-3d8e2c569e47&amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2c7b11a3a0-0dfc-49e7-b1c9-d65db207aa5d.aspx">I
drooled</a> over the announcements regarding C# 3 and LINQ.  Now we are one step
closer. Yesterday, they released a <a href="http://www.marklio.com/marklio/ct.ashx?id=bdcef32a-18ba-4dd3-8f99-3d8e2c569e47&amp;url=http%3a%2f%2fwww.microsoft.com%2fdownloads%2fdetails.aspx%3ffamilyid%3d1e902c21-340c-4d13-9f04-70eb5e3dceea%26displaylang%3den">new
preview</a> of those features that bind against the current version of the framework.
</p>
        <p>
Skeptical language junkies* should take a gander at <a href="http://www.marklio.com/marklio/ct.ashx?id=bdcef32a-18ba-4dd3-8f99-3d8e2c569e47&amp;url=http%3a%2f%2fpluralsight.com%2fblogs%2fdbox%2farchive%2f2006%2f05%2f12%2f23354.aspx">Don
Box's latest post</a> that attempts to explain what the big deal is. I agree with
some of the people saying that the syntax really gets in the way (and I feel
that way even more after spending alot of time in Ruby lately).  They need to
add a language feature that indicates whether you want the lambda or the expression,
then you can fall back on type inference to keep the typing to a minimum.
</p>
        <p>
Overall, I couldn't be more giddy about the way integrated query works, and being
able to get your hands dirty with it now is really awesome.  We're already working
with data in this way in our APIs at work, so I've been able to experiment with the
language and library features directly with some of our data and it's an absolute
dream.  <strong>They should not wait for the next version of the framework to
give us a go-live license for this.</strong></p>
        <p>
Now, this kind of thinking needs to be applied to the web stack and MS could have
a compelling alternative to Rails.
</p>
        <p>
          <em>
            <font face="Georgia">* That is, language junkies who are skeptical, not junkies
of skeptical languages.</font>
          </em>
        </p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=bdcef32a-18ba-4dd3-8f99-3d8e2c569e47" />
      </body>
      <title>More C# 3 and LINQ</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,bdcef32a-18ba-4dd3-8f99-3d8e2c569e47.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,bdcef32a-18ba-4dd3-8f99-3d8e2c569e47.aspx</link>
      <pubDate>Fri, 12 May 2006 19:38:07 GMT</pubDate>
      <description>&lt;p&gt;
During the last PDC, &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=bdcef32a-18ba-4dd3-8f99-3d8e2c569e47&amp;amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2c7b11a3a0-0dfc-49e7-b1c9-d65db207aa5d.aspx"&gt;I
drooled&lt;/a&gt; over the announcements regarding C# 3 and LINQ.&amp;nbsp; Now we are one step
closer. Yesterday, they released a &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=bdcef32a-18ba-4dd3-8f99-3d8e2c569e47&amp;amp;url=http%3a%2f%2fwww.microsoft.com%2fdownloads%2fdetails.aspx%3ffamilyid%3d1e902c21-340c-4d13-9f04-70eb5e3dceea%26displaylang%3den"&gt;new
preview&lt;/a&gt; of those features that bind against the current version of the framework.
&lt;/p&gt;
&lt;p&gt;
Skeptical language junkies* should take a gander at &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=bdcef32a-18ba-4dd3-8f99-3d8e2c569e47&amp;amp;url=http%3a%2f%2fpluralsight.com%2fblogs%2fdbox%2farchive%2f2006%2f05%2f12%2f23354.aspx"&gt;Don
Box's latest post&lt;/a&gt; that attempts to explain what the big deal is. I agree with
some of the people saying&amp;nbsp;that the syntax really gets in the way (and I feel
that way even more after spending alot of time in Ruby lately).&amp;nbsp; They need to
add a language feature that indicates whether you want the lambda or the expression,
then you can fall back on type inference to keep the typing to a minimum.
&lt;/p&gt;
&lt;p&gt;
Overall, I couldn't be more giddy about the way integrated query works, and being
able to get your hands dirty with it now is really awesome.&amp;nbsp; We're already working
with data in this way in our APIs at work, so I've been able to experiment with the
language and library features directly with some of our data and it's an absolute
dream.&amp;nbsp; &lt;strong&gt;They should not wait for the next version of the framework to
give us a go-live license for this.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Now, this kind of thinking needs to be applied to the web stack and MS could have
a compelling alternative to Rails.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;&lt;font face=Georgia&gt;* That is, language junkies who are skeptical, not junkies
of skeptical languages.&lt;/font&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=bdcef32a-18ba-4dd3-8f99-3d8e2c569e47" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,bdcef32a-18ba-4dd3-8f99-3d8e2c569e47.aspx</comments>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=cbac176e-2f0f-4e90-a066-da9f7b1c38e7</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,cbac176e-2f0f-4e90-a066-da9f7b1c38e7.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,cbac176e-2f0f-4e90-a066-da9f7b1c38e7.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=cbac176e-2f0f-4e90-a066-da9f7b1c38e7</wfw:commentRss>
      <title>Managed Xmp Parser</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,cbac176e-2f0f-4e90-a066-da9f7b1c38e7.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,cbac176e-2f0f-4e90-a066-da9f7b1c38e7.aspx</link>
      <pubDate>Sun, 12 Feb 2006 22:48:18 GMT</pubDate>
      <description>&lt;p&gt;
One of&amp;nbsp;the most popular search hits for my blog is "Managed XMP Parser".&amp;nbsp;
A while back (actually it was 1 year ago today...whoa, freaky), &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=cbac176e-2f0f-4e90-a066-da9f7b1c38e7&amp;amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2c0575ae50-07e8-4274-b7fb-2b7900a18128.aspx"&gt;I
blogged about extracting the XMP data out of my pictures&lt;/a&gt; after screwing up the
upload into Flickr.&amp;nbsp; I ended up writing my own code to pull out the XMP data.&amp;nbsp;
I mentioned making it available, but it was relatively straightforward, so I never
got around to posting it.
&lt;/p&gt;
&lt;p&gt;
In the last week, I've gotten lots of requests for the code, so here it is, uglyness
and all.&amp;nbsp; One interesting thing about my approach is that I do not rely on any
particular file format.&amp;nbsp; I simply look for the XMP markers and pull out the XML
in-between.&amp;nbsp; This means it will work on ANY file with embedded XMP.
&lt;/p&gt;
&lt;p&gt;
All the usual disclaimers apply.&amp;nbsp; I don't claim this is the best way, but it
works.&amp;nbsp; I've just plucked it out of my little date fixing app I built.&amp;nbsp;
At the end, you'll have an XPathNavigator and a namespace manager setup to run XPath
queries.&amp;nbsp; There's probably some sweet stuff the 2.0 can help us out with, but
I haven't updated it.&amp;nbsp; Enjoy:
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: teal; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;MemoryStream&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; xmpStream
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;new&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: teal"&gt;MemoryStream&lt;/span&gt;&lt;font color=#000000&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;();&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;byte&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;[]
beginPattern = &lt;/font&gt;&lt;span style="COLOR: teal"&gt;Encoding&lt;/span&gt;&lt;font color=#000000&gt;.ASCII.GetBytes(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"&amp;lt;?xpacket
begin"&lt;/span&gt;&lt;font color=#000000&gt;);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;int&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; beginIndex=0;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;bool&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; beginFound
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;false&lt;/span&gt;&lt;font color=#000000&gt;;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;byte&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;[]
beginStopPattern = &lt;/font&gt;&lt;span style="COLOR: teal"&gt;Encoding&lt;/span&gt;&lt;font color=#000000&gt;.ASCII.GetBytes(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"&amp;gt;\n"&lt;/span&gt;&lt;font color=#000000&gt;);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;int&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; beginStopIndex
= 0;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;bool&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; xmlStartFound
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;false&lt;/span&gt;&lt;font color=#000000&gt;;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;byte&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;[]
endPattern = &lt;/font&gt;&lt;span style="COLOR: teal"&gt;Encoding&lt;/span&gt;&lt;font color=#000000&gt;.ASCII.GetBytes(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"&amp;lt;?xpacket
end"&lt;/span&gt;&lt;font color=#000000&gt;);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;int&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; endIndex=0;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;bool&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; endFound
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;false&lt;/span&gt;&lt;font color=#000000&gt;;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;bool&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; backedUp
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;false&lt;/span&gt;&lt;font color=#000000&gt;;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;using&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; (&lt;/font&gt;&lt;span style="COLOR: teal"&gt;Stream&lt;/span&gt;&lt;font color=#000000&gt; stream
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;new&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: teal"&gt;FileStream&lt;/span&gt;&lt;font color=#000000&gt;(path, &lt;/font&gt;&lt;span style="COLOR: teal"&gt;FileMode&lt;/span&gt;&lt;font color=#000000&gt;.Open))
{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;int&lt;/span&gt;&lt;font color=#000000&gt; data;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;while&lt;/span&gt;&lt;font color=#000000&gt; ((data
= stream.ReadByte()) != -1) {&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;byte&lt;/span&gt;&lt;font color=#000000&gt; b
= (&lt;/font&gt;&lt;span style="COLOR: blue"&gt;byte&lt;/span&gt;&lt;font color=#000000&gt;)data;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt;&lt;font color=#000000&gt; (!beginFound)
{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 3"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt;&lt;font color=#000000&gt; (b
== beginPattern[beginIndex]) {&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;beginIndex++;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 4"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt;&lt;font color=#000000&gt; (beginIndex
&amp;gt;= beginPattern.Length) {&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 5"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;beginFound
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;true&lt;/span&gt;&lt;font color=#000000&gt;;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 3"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;else&lt;/span&gt;&lt;font color=#000000&gt; {&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 4"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt;&lt;font color=#000000&gt; (beginIndex
!= 0) {&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 5"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;beginIndex
= 0;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 5"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;stream.Seek(-1, &lt;/font&gt;&lt;span style="COLOR: teal"&gt;SeekOrigin&lt;/span&gt;&lt;font color=#000000&gt;.Current);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;else&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt;&lt;font color=#000000&gt; (!xmlStartFound)
{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 3"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt;&lt;font color=#000000&gt; (b
== beginStopPattern[beginStopIndex]) {&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;beginStopIndex++;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 4"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt;&lt;font color=#000000&gt; (beginStopIndex
&amp;gt;= beginStopPattern.Length) {&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 5"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;xmlStartFound
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;true&lt;/span&gt;&lt;font color=#000000&gt;;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 3"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;else&lt;/span&gt;&lt;font color=#000000&gt; {&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 4"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt;&lt;font color=#000000&gt; (beginStopIndex
!= 0) {&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 5"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;beginStopIndex
= 0;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 5"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;stream.Seek(-1, &lt;/font&gt;&lt;span style="COLOR: teal"&gt;SeekOrigin&lt;/span&gt;&lt;font color=#000000&gt;.Current);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;else&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt;&lt;font color=#000000&gt; (!endFound)
{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 3"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: green"&gt;//load
up the memorystream&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 3"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt;&lt;font color=#000000&gt; (backedUp)
{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;backedUp
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;false&lt;/span&gt;&lt;font color=#000000&gt;;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 3"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;else&lt;/span&gt;&lt;font color=#000000&gt; {&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;xmpStream.WriteByte(b);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 3"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt;&lt;font color=#000000&gt; (b
== endPattern[endIndex]) {&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;endIndex++;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 4"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt;&lt;font color=#000000&gt; (endIndex
&amp;gt;= endPattern.Length) {&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 5"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;endFound
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;true&lt;/span&gt;&lt;font color=#000000&gt;;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 5"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;xmpStream.SetLength(xmpStream.Length-endPattern.Length);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 5"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;break&lt;/span&gt;&lt;font color=#000000&gt;;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 3"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;else&lt;/span&gt;&lt;font color=#000000&gt; {&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 4"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt;&lt;font color=#000000&gt; (endIndex
!= 0) {&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 5"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;endIndex
= 0;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 5"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;stream.Seek(-1, &lt;/font&gt;&lt;span style="COLOR: teal"&gt;SeekOrigin&lt;/span&gt;&lt;font color=#000000&gt;.Current);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 5"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;backedUp
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;true&lt;/span&gt;&lt;font color=#000000&gt;;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;if&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; (!endFound)
{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: teal"&gt;Console&lt;/span&gt;&lt;font color=#000000&gt;.WriteLine(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"No
XMP data found"&lt;/span&gt;&lt;font color=#000000&gt;);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;break&lt;/span&gt;&lt;font color=#000000&gt;;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;//load
up the xmp&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;xmpStream.Position
= 0;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: teal; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;XPathDocument&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; xmpDocument
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;new&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: teal"&gt;XPathDocument&lt;/span&gt;&lt;font color=#000000&gt;(xmpStream);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: teal; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;XPathNavigator&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; xmpNav
= xmpDocument.CreateNavigator();&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: teal; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;XmlNamespaceManager&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; nsManager
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;new&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: teal"&gt;XmlNamespaceManager&lt;/span&gt;&lt;font color=#000000&gt;(xmpNav.NameTable);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;nsManager.AddNamespace(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"x"&lt;/span&gt;&lt;font color=#000000&gt;, &lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"adobe:ns:meta/"&lt;/span&gt;&lt;font color=#000000&gt;);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;nsManager.AddNamespace(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"rdf"&lt;/span&gt;&lt;font color=#000000&gt;, &lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"http://www.w3.org/1999/02/22-rdf-syntax-ns#"&lt;/span&gt;&lt;font color=#000000&gt;);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;nsManager.AddNamespace(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"iX"&lt;/span&gt;&lt;font color=#000000&gt;, &lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"http://ns.adobe.com/iX/1.0/"&lt;/span&gt;&lt;font color=#000000&gt;);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;nsManager.AddNamespace(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"crs"&lt;/span&gt;&lt;font color=#000000&gt;, &lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"http://ns.adobe.com/camera-raw-settings/1.0/"&lt;/span&gt;&lt;font color=#000000&gt;);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;nsManager.AddNamespace(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"exif"&lt;/span&gt;&lt;font color=#000000&gt;, &lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"http://ns.adobe.com/exif/1.0/"&lt;/span&gt;&lt;font color=#000000&gt;);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;nsManager.AddNamespace(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"aux"&lt;/span&gt;&lt;font color=#000000&gt;, &lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"http://ns.adobe.com/exif/1.0/aux/"&lt;/span&gt;&lt;font color=#000000&gt;);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;nsManager.AddNamespace(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"pdf"&lt;/span&gt;&lt;font color=#000000&gt;, &lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"http://ns.adobe.com/pdf/1.3/"&lt;/span&gt;&lt;font color=#000000&gt;);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;nsManager.AddNamespace(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"photoshop"&lt;/span&gt;&lt;font color=#000000&gt;, &lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"http://ns.adobe.com/photoshop/1.0/"&lt;/span&gt;&lt;font color=#000000&gt;);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;nsManager.AddNamespace(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"tiff"&lt;/span&gt;&lt;font color=#000000&gt;, &lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"http://ns.adobe.com/tiff/1.0/"&lt;/span&gt;&lt;font color=#000000&gt;);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;nsManager.AddNamespace(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"xap"&lt;/span&gt;&lt;font color=#000000&gt;, &lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"http://ns.adobe.com/xap/1.0/"&lt;/span&gt;&lt;font color=#000000&gt;);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;nsManager.AddNamespace(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"xapMM"&lt;/span&gt;&lt;font color=#000000&gt;, &lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"http://ns.adobe.com/xap/1.0/mm/"&lt;/span&gt;&lt;font color=#000000&gt;);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;nsManager.AddNamespace(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"dc"&lt;/span&gt;&lt;font color=#000000&gt;, &lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"http://purl.org/dc/elements/1.1/"&lt;/span&gt;&lt;font color=#000000&gt;);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: teal; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;XPathExpression&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; dateExpr
= xmpNav.Compile(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"string(/x:xmpmeta/rdf:RDF/rdf:Description/exif:DateTimeOriginal)"&lt;/span&gt;&lt;font color=#000000&gt;);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;dateExpr.SetContext(nsManager);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;string&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; dateTimeStr
= (&lt;/font&gt;&lt;span style="COLOR: blue"&gt;string&lt;/span&gt;&lt;font color=#000000&gt;)xmpNav.Evaluate(dateExpr);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: teal; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;DateTime&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; date
= &lt;/font&gt;&lt;span style="COLOR: teal"&gt;XmlConvert&lt;/span&gt;&lt;font color=#000000&gt;.ToDateTime(dateTimeStr);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
&lt;o:p&gt;
&lt;font face="Times New Roman" color=#000000 size=3&gt;&amp;nbsp;&lt;/font&gt;
&lt;/o:p&gt;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=cbac176e-2f0f-4e90-a066-da9f7b1c38e7" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,cbac176e-2f0f-4e90-a066-da9f7b1c38e7.aspx</comments>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=16c93549-8e91-407f-b969-7857e2a7fc01</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,16c93549-8e91-407f-b969-7857e2a7fc01.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,16c93549-8e91-407f-b969-7857e2a7fc01.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=16c93549-8e91-407f-b969-7857e2a7fc01</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Back the the days of .NET 1.1, you'd use a Hashtable to store values with a fast lookup
using a key.  Hashtable used a single array of "buckets", which stored the key,
value, and a collision index.  The index to the the bucket array is a transform
of the hashcode of the key (unless there's a collision).  Long story short, there
was no stable ordering to the values in a Hashtable (technically, the order is super-important
to the algorithm, but it's not useful on the outside).
</p>
        <p>
Fast-forward to 2.0, we have the Generic Dictionary.  It's algorithm is quite
a bit different.  It has an array of Entry&lt;Key, Value&gt;, a private nested
class similar to bucket in the Hashtable.  But, the "bucket" data is stored in
a separate array of int, which holds the index into the Entry array for that hash. 
When you add something to a Dictionary, it is simply added to the Entry array, and
the bucket array is the one that's updated and possibly re-ordered.  Long story
short, there IS meaning to the order you get from a generic Dictionary (using the
enumerator).  It's the order you added them.  This subtle change adds alot
of value to Dictionary in my opinion.
</p>
        <p>
It was just a very interesting realization to me, and I thought someone else might
find it useful.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=16c93549-8e91-407f-b969-7857e2a7fc01" />
      </body>
      <title>Generic Dictionary order</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,16c93549-8e91-407f-b969-7857e2a7fc01.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,16c93549-8e91-407f-b969-7857e2a7fc01.aspx</link>
      <pubDate>Thu, 26 Jan 2006 17:03:31 GMT</pubDate>
      <description>&lt;p&gt;
Back the the days of .NET 1.1, you'd use a Hashtable to store values with a fast lookup
using a key.&amp;nbsp; Hashtable used a single array of "buckets", which stored the key,
value, and a collision index.&amp;nbsp; The index to the the bucket array is a transform
of the hashcode of the key (unless there's a collision).&amp;nbsp; Long story short, there
was no stable ordering to the values in a Hashtable (technically, the order is super-important
to the algorithm, but it's not useful on the outside).
&lt;/p&gt;
&lt;p&gt;
Fast-forward to 2.0, we have the Generic Dictionary.&amp;nbsp; It's algorithm is quite
a bit different.&amp;nbsp; It has an array of Entry&amp;lt;Key, Value&amp;gt;, a private nested
class similar to bucket in the Hashtable.&amp;nbsp; But, the "bucket" data is stored in
a separate array of int, which holds the index into the Entry array for that hash.&amp;nbsp;
When you add something to a Dictionary, it is simply added to the Entry array, and
the bucket array is the one that's updated and possibly re-ordered.&amp;nbsp; Long story
short, there IS meaning to the order you get from a generic Dictionary (using the
enumerator).&amp;nbsp; It's the order you added them.&amp;nbsp; This subtle change adds alot
of value to Dictionary in my opinion.
&lt;/p&gt;
&lt;p&gt;
It was just a very interesting realization to me, and I thought someone else might
find it useful.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=16c93549-8e91-407f-b969-7857e2a7fc01" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,16c93549-8e91-407f-b969-7857e2a7fc01.aspx</comments>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=65a04754-ffe7-4a4d-9078-8ca127a6750f</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,65a04754-ffe7-4a4d-9078-8ca127a6750f.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,65a04754-ffe7-4a4d-9078-8ca127a6750f.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=65a04754-ffe7-4a4d-9078-8ca127a6750f</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
As <a href="http://www.marklio.com/marklio/ct.ashx?id=65a04754-ffe7-4a4d-9078-8ca127a6750f&amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2cd3026398-6692-4f01-b14a-30eda90c0834.aspx">I
mentioned earlier</a>, I've been playing with WF.  When debugging in Visual Studio,
a program running a workflow pretty much uses 99% of CPU the whole time.  I thought
that was pretty scary, especially since I had alot of Delay activities in my workflow. 
Well, not to worry, running the .EXE outside of devenv gives you what you expect,
a very well-behaved program.
</p>
        <p>
I suspect it has to do with the sweet debugging stuff that's built into the workflow
designer surface.  You can add breakpoints to activities.  It's pretty cool,
despite crashing on a regular basis.  Hopefully, they'll fix this before RTM.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=65a04754-ffe7-4a4d-9078-8ca127a6750f" />
      </body>
      <title>Don't let Windows Workflow debugging scare you</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,65a04754-ffe7-4a4d-9078-8ca127a6750f.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,65a04754-ffe7-4a4d-9078-8ca127a6750f.aspx</link>
      <pubDate>Fri, 06 Jan 2006 16:00:06 GMT</pubDate>
      <description>&lt;p&gt;
As &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=65a04754-ffe7-4a4d-9078-8ca127a6750f&amp;amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2cd3026398-6692-4f01-b14a-30eda90c0834.aspx"&gt;I
mentioned earlier&lt;/a&gt;, I've been playing with WF.&amp;nbsp; When debugging in Visual Studio,
a program running a workflow pretty much uses 99% of CPU the whole time.&amp;nbsp; I thought
that was pretty scary, especially since I had alot of Delay activities in my workflow.&amp;nbsp;
Well, not to worry, running the .EXE outside of devenv gives you what you expect,
a very well-behaved program.
&lt;/p&gt;
&lt;p&gt;
I suspect it has to do with the sweet debugging stuff that's built into the workflow
designer surface.&amp;nbsp; You can add breakpoints to activities.&amp;nbsp; It's pretty cool,
despite crashing on a regular basis.&amp;nbsp; Hopefully, they'll fix this before RTM.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=65a04754-ffe7-4a4d-9078-8ca127a6750f" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,65a04754-ffe7-4a4d-9078-8ca127a6750f.aspx</comments>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=d3026398-6692-4f01-b14a-30eda90c0834</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,d3026398-6692-4f01-b14a-30eda90c0834.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,d3026398-6692-4f01-b14a-30eda90c0834.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=d3026398-6692-4f01-b14a-30eda90c0834</wfw:commentRss>
      <title>Playing with Windows Workflow Foundation</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,d3026398-6692-4f01-b14a-30eda90c0834.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,d3026398-6692-4f01-b14a-30eda90c0834.aspx</link>
      <pubDate>Thu, 05 Jan 2006 19:46:27 GMT</pubDate>
      <description>&lt;p&gt;
I've had a bit of time this week to dive into WF (formerly WWF... he he).&amp;nbsp; I'm
very interested in utilizing this both professionally and personally.&amp;nbsp; In my
experience, a HUGE amount of the software I interact with and write deals with workflow.&amp;nbsp;
I need more than one hand to count the pieces of software I deal with at work that
attempt to give the user a design surface to create workflow&amp;nbsp;on.&amp;nbsp; Most of
them fail pretty miserably.&amp;nbsp; That's why I was delighted that the WF designer
was so extensible and reusable.
&lt;/p&gt;
&lt;p&gt;
After orienting myself with the concepts of WF, I set out to extend the base SequentialWorkflow
to wrap some custom behavior around the execution of the workflow.&amp;nbsp; I immediately
ran into problems.&amp;nbsp; It seems that if you inherit from SequentialWorkflow, the
project immediately thinks you are going to use the designer to create a workflow,
rather than build a base type that will be used to build workflows in other projects.&amp;nbsp;
It immediately starts throwing around validation messages like:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;Activity 'BlahBlahBlah' validation failed: Property 'ID'
not set.&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Well, of course it's not set, I'm not even remotely trying to create one yet.&amp;nbsp;
So, I add the following brain-dead code in the constructor:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;if&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; (&lt;/font&gt;&lt;span style="COLOR: blue"&gt;this&lt;/span&gt;&lt;font color=#000000&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;.DesignMode)
{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;this&lt;/span&gt;&lt;font color=#000000&gt;.ID
= &lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"FakeID"&lt;/span&gt;&lt;font color=#000000&gt;;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
This gets rid of the validation error, but now it gripes that my class is not partial,
so I slap a partial modifier on it and let it go.&amp;nbsp; Finally, it compiles.
&lt;/p&gt;
&lt;p&gt;
Once I figure that out, I'm golden and things run fairly smoothly.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=d3026398-6692-4f01-b14a-30eda90c0834" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,d3026398-6692-4f01-b14a-30eda90c0834.aspx</comments>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=30bdb0e9-1268-41b1-9af4-e8e166ef0220</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,30bdb0e9-1268-41b1-9af4-e8e166ef0220.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,30bdb0e9-1268-41b1-9af4-e8e166ef0220.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=30bdb0e9-1268-41b1-9af4-e8e166ef0220</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
The two main High Definition standards are 720p and 1080i.  Since there is plenty
of information on the 2, I will not go into detail on them individually.  What
there <strong>isn't</strong> alot of is objective, well-reasoned explanations of which
one is better.  Mostly, this is because it is not a simple topic, and the winner
depends largely on the context of the question.  Another reason this is so hotly
debated is that people spend alot of money on HDTV's and that causes people to become
zealots of whatever particular technology they've embraced. I'll try to compare the
two within each of the important contexts, without personal bias.
</p>
        <p>
Let's start with the fundamental question.  From a HDTV technology perspective, which
is better?  The answer is, <strong>they are the same</strong>.  Before you
leave a comment on how stupid I am, keep reading.  Fundamentally, we're talking
about how much data can be displayed at a time.  For TV, that is limited far
more by transmission bandwidth than anything else.  To maintain that bandwidth,
the signal is compressed in a lossy fashion <em>(see update below)</em>. In either
format, you're going to get roughly the same "picture quality" watching TV.
</p>
        <p>
Now, you're saying "shut-up, idiot.  One has got to be better.  Why won't
my TV do 720p (or 1080i) if they are the same?". This is where the argument
gets interesting.  The signal formats were created for "analog" TV technology,
namely CRTs.  For CRTs, it's all about frequency.  (How many lines can you
draw per second) 720p has more lines per second.  The problem is, you're still
bandwidth limited, whatever that limit may be. Horizontal "resolution" comes
down to bandwidth.  Any increase in bandwidth basically gives you more capacity
for horizontal resolution, so again the two are the same.  The problem is,
many HD sets are based on technologies with a "native resolution", meaning the TV
is locked in to a certain resolution.  In these cases, the interlacing trick
used by 1080i to gain temporal resolution at the cost of spatial resolution is
useless.  [Added:] <em>Many CRT-based HD sets cannot do 720p because it requires
a higher horizontal refresh rate and the flyback circuit capable of 1080i is not capable
of that speed (in short, you got screwed (myself included) to increase their profit
margin). 1080i is refresh frequency comparable to 540p (if it existed as a standard).</em></p>
        <p>
So, the result is that most HD sets have a native resolution at (or near) 720p. 
So, for those sets, a 720p signal matches the native resolution of the set and "looks"
better.  There's alot of hype around 1080p sets, capable of displaying, you guessed
it, a 1080p signal, which only really exists as the output of a PC at 1920x1080, which
brings me to my next point.
</p>
        <p>
Since basically all HD content is stored digitally, we're not just looking at lines
of resolution, we've got frame sizes.  So a 720p frame is 1280x720, and you get
2 per second.  That's 1,843,200 pixels per second.  A 1080i frame is 1920x1080,
but you only get 1 per second. That's 2,073,600 pixels per second.  <strong>So,
compression and bandwidth aside, dealing with digital signal sources, you're getting
more data (in the form of pixels per second) with 1080i than you are from 720p. 
If that's the definition of better, then 1080i is better.</strong></p>
        <p>
But, as I mentioned before for fixed resolution TV technology (anything but CRT),
it takes a 1080p set to show 1080i in all it's glory.  Otherwise, 720p will probably
look better due to the down-conversion resampling. Clear as mud, eh?  Well, I
hope this clears it up for at least one person. [Added:] A signal will almost always
look better in its native form.  Whenever there is a resampling step in up/down
converting, you're going to have some degradation due to aliasing.
</p>
        <p>
          <em>[Added:] I owned a 1080p DLP set for a few short days, and it was by far the prettiest
thing I've seen.  it displayed both 1080i and 720p signals beautifully. 
I sent it back, though.  All the upconverting in the video pipeline introduced
a noticable delay that made playing video games very frustrating. :)</em>
        </p>
        <p>
          <em>[UPDATE:] I had a comment asking about the lossy compression applied to video. 
I'm referring to the digital compression that the video signal undergoes as part of
the ATSC standard.  It uses MPEG2 compression (basically the same used for DVDs)
to reduce the digital bandwidth (and therefore the analog bandwidth) that the video
signal takes up so it fits in the "channel" (6MHz wide if I remember correctly). 
This particular compression degrades picture quality (the amount can be controlled). 
It is both a spatial and temporal compression, and gives very dramatic compression
ratios.  Cable companies have more bandwidth to work with, but they usually pack
the crap in as tight as they can rather than giving us better quality...jerks.</em>
        </p>
        <p>
          <em>Note, there is also some "analog" compression going on as well to squeeze
the ~20Mbit/sec digital signal into the 6Mhz channel.  The ATSC standard uses
an 8-bit "vestigial side band" modulation (8VSB), while cable companies use a form
of Quadrature Amplitude Modulation (64-QAM).  Both are beyond the scope of this
article and neither of these come into play in picture quality as they are lossless
forms of compression.</em>
        </p>
        <p>
          <em>If you haven't guessed, I did a research paper on HDTV back in college.</em>
        </p>
        <p>
          <em>[Yet another UPDATE:]  Want some hands-on proof?  Go download the 720p
(146MB) and 1080i (211MB) versions of the King Kong movie trailer from <a href="http://www.marklio.com/marklio/ct.ashx?id=30bdb0e9-1268-41b1-9af4-e8e166ef0220&amp;url=http%3a%2f%2ftrailers.apple.com%2ftrailers%2funiversal%2fking_kong%2fhd%2f">Apple's
site</a>.  Compare the file sizes and then open them both, and you decide which
one shows you more "data" (my definition of "better").</em>
        </p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=30bdb0e9-1268-41b1-9af4-e8e166ef0220" />
      </body>
      <title>720p vs. 1080i</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,30bdb0e9-1268-41b1-9af4-e8e166ef0220.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,30bdb0e9-1268-41b1-9af4-e8e166ef0220.aspx</link>
      <pubDate>Tue, 27 Dec 2005 22:07:39 GMT</pubDate>
      <description>&lt;p&gt;
The two main High Definition standards are 720p and 1080i.&amp;nbsp; Since there is plenty
of information on the 2, I will not go into detail on them individually.&amp;nbsp; What
there &lt;strong&gt;isn't&lt;/strong&gt; alot of is objective, well-reasoned explanations of which
one is better.&amp;nbsp; Mostly, this is because it is not a simple topic, and the winner
depends largely on the context of the question.&amp;nbsp; Another reason this is so hotly
debated is that people spend alot of money on HDTV's and that causes people to become
zealots of whatever particular technology they've embraced. I'll try to compare the
two within each of the important contexts, without personal bias.
&lt;/p&gt;
&lt;p&gt;
Let's start with the fundamental question.&amp;nbsp; From a HDTV&amp;nbsp;technology perspective,&amp;nbsp;which
is better?&amp;nbsp; The answer is, &lt;strong&gt;they are the same&lt;/strong&gt;.&amp;nbsp; Before you
leave a comment on how stupid I am, keep reading.&amp;nbsp; Fundamentally, we're talking
about how much data can be displayed at a time.&amp;nbsp; For TV, that is limited far
more by transmission bandwidth than anything else.&amp;nbsp; To maintain that bandwidth,
the signal is compressed in a lossy fashion &lt;em&gt;(see update below)&lt;/em&gt;. In either
format, you're going to get roughly the same "picture quality" watching TV.
&lt;/p&gt;
&lt;p&gt;
Now, you're saying "shut-up, idiot.&amp;nbsp; One has got to be better.&amp;nbsp; Why won't
my TV do 720p (or 1080i)&amp;nbsp;if they are the same?".&amp;nbsp;This is where the argument
gets interesting.&amp;nbsp; The signal formats were created for "analog" TV technology,
namely CRTs.&amp;nbsp; For CRTs, it's all about frequency.&amp;nbsp; (How many lines can you
draw per second) 720p has more lines per second.&amp;nbsp; The problem is, you're still
bandwidth limited, whatever that limit may be.&amp;nbsp;Horizontal "resolution" comes
down to bandwidth.&amp;nbsp; Any increase in bandwidth basically gives you more&amp;nbsp;capacity
for&amp;nbsp;horizontal resolution, so again the two are the same.&amp;nbsp; The problem is,
many HD sets are based on technologies with a "native resolution", meaning the TV
is locked in to a certain resolution.&amp;nbsp; In these cases, the interlacing trick
used by 1080i&amp;nbsp;to gain temporal resolution at the cost of spatial resolution&amp;nbsp;is
useless.&amp;nbsp; [Added:] &lt;em&gt;Many CRT-based HD sets cannot do 720p because it requires
a higher horizontal refresh rate and the flyback circuit capable of 1080i is not capable
of that speed (in short, you got screwed (myself included) to increase their profit
margin). 1080i is refresh frequency comparable to 540p (if it existed as a standard).&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
So, the result is that most HD sets have a native resolution at (or near) 720p.&amp;nbsp;
So, for those sets, a 720p signal matches the native resolution of the set and "looks"
better.&amp;nbsp; There's alot of hype around 1080p sets, capable of displaying, you guessed
it, a 1080p signal, which only really exists as the output of a PC at 1920x1080, which
brings me to my next point.
&lt;/p&gt;
&lt;p&gt;
Since basically all HD content is stored digitally, we're not just looking at lines
of resolution, we've got frame sizes.&amp;nbsp; So a 720p frame is 1280x720, and you get
2 per second.&amp;nbsp; That's 1,843,200 pixels per second.&amp;nbsp; A 1080i frame is 1920x1080,
but you only get 1 per second. That's 2,073,600 pixels per second.&amp;nbsp; &lt;strong&gt;So,
compression and bandwidth aside, dealing with digital signal sources, you're getting
more data (in the form of pixels per second) with 1080i than you are from 720p.&amp;nbsp;
If that's the definition of better, then 1080i is better.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
But, as I mentioned before for fixed resolution TV technology (anything but CRT),
it takes a 1080p set to show 1080i in all it's glory.&amp;nbsp; Otherwise, 720p will probably
look better due to the down-conversion resampling. Clear as mud, eh?&amp;nbsp; Well, I
hope this clears it up for at least one person. [Added:] A signal will almost always
look better in its native form.&amp;nbsp; Whenever there is a resampling step in up/down
converting, you're going to have some degradation due to aliasing.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;[Added:] I owned a 1080p DLP set for a few short days, and it was by far the prettiest
thing I've seen.&amp;nbsp; it displayed both 1080i and 720p signals beautifully.&amp;nbsp;
I sent it back, though.&amp;nbsp; All the upconverting in the video pipeline introduced
a noticable delay that made playing video games very frustrating. :)&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;[UPDATE:] I had a comment asking about the lossy compression applied to video.&amp;nbsp;
I'm referring to the digital compression that the video signal undergoes as part of
the ATSC standard.&amp;nbsp; It uses MPEG2 compression (basically the same used for DVDs)
to reduce the digital bandwidth (and therefore the analog bandwidth) that the video
signal takes up so it fits in the "channel" (6MHz wide if I remember correctly).&amp;nbsp;
This particular compression degrades picture quality (the amount can be&amp;nbsp;controlled).&amp;nbsp;
It is both a spatial and temporal compression, and gives very dramatic compression
ratios.&amp;nbsp; Cable companies have more bandwidth to work with, but they usually pack
the crap in as tight as they can rather than giving us better quality...jerks.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Note, there is also&amp;nbsp;some "analog" compression going on as well to squeeze
the ~20Mbit/sec digital signal into the 6Mhz channel.&amp;nbsp; The ATSC standard uses
an 8-bit "vestigial side band" modulation (8VSB), while cable companies use a form
of Quadrature Amplitude Modulation (64-QAM).&amp;nbsp; Both are beyond the scope of this
article and neither of these come into play in picture quality as they are lossless
forms of compression.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;If you haven't guessed, I did a research paper on HDTV back in college.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;[Yet another UPDATE:]&amp;nbsp; Want some hands-on proof?&amp;nbsp; Go download the 720p
(146MB)&amp;nbsp;and 1080i (211MB)&amp;nbsp;versions of the King Kong movie trailer from &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=30bdb0e9-1268-41b1-9af4-e8e166ef0220&amp;amp;url=http%3a%2f%2ftrailers.apple.com%2ftrailers%2funiversal%2fking_kong%2fhd%2f"&gt;Apple's
site&lt;/a&gt;.&amp;nbsp; Compare the file sizes and then open them both, and you decide which
one shows you more "data" (my definition of "better").&lt;/em&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=30bdb0e9-1268-41b1-9af4-e8e166ef0220" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,30bdb0e9-1268-41b1-9af4-e8e166ef0220.aspx</comments>
      <category>Fun</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=25067941-46b9-49f9-9a0b-d10a066a5c06</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,25067941-46b9-49f9-9a0b-d10a066a5c06.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,25067941-46b9-49f9-9a0b-d10a066a5c06.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=25067941-46b9-49f9-9a0b-d10a066a5c06</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Another geeky post.
</p>
        <p>
We built our own query system several years ago.  It used the concept of "query
by example" with templates that were interpreted into SQL.  You could generate
the equivalent of an "IN" clause by assigning something that implemented System.Collections.ICollection
to a template property.  Recently, with the introduction of generics and the
generic collections, we decided to relax that contract to IEnumerable since that's
really the least common denominator of all collections.  This produced some hilarious
results.  As you can imagine, anywhere where we were using strings to specify
template values, they were being interpreted as collections of characters.  This
manifested itself mostly by having queries return nothing, since our system properly
handled Chars and treated them as strings.
</p>
        <p>
But, this reminded me of a similar incident a few years ago that involved a framework
that rendered objects as comma-separated values. So, instead of:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
Mark, Miller
</p>
        </blockquote>
        <p>
You'd get:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
M, a, r, k, M, i, l, l, e, r
</p>
        </blockquote>
        <p>
I thought since I had been bitten twice, I would write it down.  I usually don't
forget stuff I take the time to write down.
</p>
        <p>
So, the moral of the story: Remember that even though System.String implements System.Collections.IEnumerable
(and now System.Collections.Generic.IEnumerable&lt;System.Char&gt;), you usually don't
want to treat it as a collection.  You may need to special-case it.
</p>
        <p>
Anyone else think of another type like this?
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=25067941-46b9-49f9-9a0b-d10a066a5c06" />
      </body>
      <title>The hilarious consequences of System.String implementing IEnumerable</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,25067941-46b9-49f9-9a0b-d10a066a5c06.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,25067941-46b9-49f9-9a0b-d10a066a5c06.aspx</link>
      <pubDate>Tue, 01 Nov 2005 20:23:02 GMT</pubDate>
      <description>&lt;p&gt;
Another geeky post.
&lt;/p&gt;
&lt;p&gt;
We built our own query system several years ago.&amp;nbsp; It used the concept of "query
by example" with templates that were interpreted into SQL.&amp;nbsp; You could generate
the equivalent of an "IN" clause by assigning&amp;nbsp;something that implemented System.Collections.ICollection
to a template property.&amp;nbsp; Recently, with the introduction of generics and the
generic collections, we decided to relax that contract to IEnumerable since that's
really the least common denominator of all collections.&amp;nbsp; This produced some hilarious
results.&amp;nbsp; As you can imagine, anywhere where we were using strings to specify
template values, they were being interpreted as collections of characters.&amp;nbsp; This
manifested itself mostly by having queries return nothing, since our system properly
handled Chars and treated them as strings.
&lt;/p&gt;
&lt;p&gt;
But, this reminded me of a similar incident a few years ago that involved a framework
that rendered objects as comma-separated values. So, instead of:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
Mark, Miller
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
You'd get:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
M, a, r, k, M, i, l, l, e, r
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
I thought since I had been bitten twice, I would write it down.&amp;nbsp; I usually don't
forget stuff I take the time to write down.
&lt;/p&gt;
&lt;p&gt;
So, the moral of the story: Remember that even though System.String implements System.Collections.IEnumerable
(and now System.Collections.Generic.IEnumerable&amp;lt;System.Char&amp;gt;), you usually don't
want to treat it as a collection.&amp;nbsp; You may need to special-case it.
&lt;/p&gt;
&lt;p&gt;
Anyone else think of another type like this?
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=25067941-46b9-49f9-9a0b-d10a066a5c06" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,25067941-46b9-49f9-9a0b-d10a066a5c06.aspx</comments>
      <category>Crazy stuff</category>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=50f8adeb-bef6-43c5-a48e-81575ac99a4a</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,50f8adeb-bef6-43c5-a48e-81575ac99a4a.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,50f8adeb-bef6-43c5-a48e-81575ac99a4a.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=50f8adeb-bef6-43c5-a48e-81575ac99a4a</wfw:commentRss>
      <title>Updating my "multi-request-safe" File-based ViewState persistence for Whidbey</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,50f8adeb-bef6-43c5-a48e-81575ac99a4a.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,50f8adeb-bef6-43c5-a48e-81575ac99a4a.aspx</link>
      <pubDate>Mon, 22 Aug 2005 21:21:14 GMT</pubDate>
      <description>&lt;p&gt;
A while back, I showed you my &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=50f8adeb-bef6-43c5-a48e-81575ac99a4a&amp;amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2caf76f1a0-2d44-44c3-bfb5-029740b8e683.aspx"&gt;file-based
viewstate persistence solution&lt;/a&gt;.&amp;nbsp; Thanks to Google search hits&amp;nbsp;and traffic
from &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=50f8adeb-bef6-43c5-a48e-81575ac99a4a&amp;amp;url=http%3a%2f%2fwww.hanselman.com%2fblog%2fAMultirequestsafeViewStatePersister.aspx"&gt;Scott
Hanselman's analysis&lt;/a&gt;, it's been one of my more popular entries.&amp;nbsp; With ASP.net's
improvements in this area, I felt that it was due for an update.&amp;nbsp; So, here's
a quick whack at it.&amp;nbsp; The usual disclaimers apply.
&lt;/p&gt;
&lt;p&gt;
2.0 adds the notion of "control state" to state persistence, which is very cool.&amp;nbsp;
It's an opt-in mechanism for things that need to survive postbacks even if ViewState
is turned off.&amp;nbsp; In addition, there's some new&amp;nbsp;flexibility with page adapters
and such, but we'll ignore that complexity for now and go for a direct port of my
old sample, but include the new ControlState mechanism.
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;class&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: teal"&gt;FileBasedPageStatePersister&lt;/span&gt;&lt;font color=#000000&gt; : &lt;/font&gt;&lt;span style="COLOR: teal"&gt;HiddenFieldPageStatePersister&lt;/span&gt;&lt;font color=#000000&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt; {&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;public&lt;/span&gt;&lt;font color=#000000&gt; FileBasedPageStatePersister(&lt;/font&gt;&lt;span style="COLOR: teal"&gt;Page&lt;/span&gt;&lt;font color=#000000&gt; page)
: &lt;/font&gt;&lt;span style="COLOR: blue"&gt;base&lt;/span&gt;&lt;font color=#000000&gt;(page) {}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;
&lt;o:p&gt;
&lt;font color=#000000&gt;&amp;nbsp;&lt;/font&gt;
&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;public&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;override&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;void&lt;/span&gt;&lt;font color=#000000&gt; Load()
{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: gray"&gt;//let
the base class do its thing&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;base&lt;/span&gt;&lt;font color=#000000&gt;.Load();&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: gray"&gt;//get
the control state&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;object&lt;/span&gt;&lt;font color=#000000&gt; baseControlState
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;base&lt;/span&gt;&lt;font color=#000000&gt;.ControlState;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt;&lt;font color=#000000&gt; (baseControlState
!= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;null&lt;/span&gt;&lt;font color=#000000&gt;) {&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 3"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: gray"&gt;//the
control state should be our Guid&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 3"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: teal"&gt;Guid&lt;/span&gt;&lt;font color=#000000&gt; guid
= (&lt;/font&gt;&lt;span style="COLOR: teal"&gt;Guid&lt;/span&gt;&lt;font color=#000000&gt;)baseControlState;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 3"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: gray"&gt;//read
the contents of the file and set the two states&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 3"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;using&lt;/span&gt;&lt;font color=#000000&gt; (&lt;/font&gt;&lt;span style="COLOR: teal"&gt;TextReader&lt;/span&gt;&lt;font color=#000000&gt; reader
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;new&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: teal"&gt;StreamReader&lt;/span&gt;&lt;font color=#000000&gt;(CreateOfflineViewStateFilePath(guid)))
{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 4"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: teal"&gt;Pair&lt;/span&gt;&lt;font color=#000000&gt; pair
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;this&lt;/span&gt;&lt;font color=#000000&gt;.StateFormatter.Deserialize(reader.ReadToEnd()) &lt;/font&gt;&lt;span style="COLOR: blue"&gt;as&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: teal"&gt;Pair&lt;/span&gt;&lt;font color=#000000&gt;;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 4"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;base&lt;/span&gt;&lt;font color=#000000&gt;.ViewState
= pair.First;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 4"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;base&lt;/span&gt;&lt;font color=#000000&gt;.ControlState
= pair.Second;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;
&lt;o:p&gt;
&lt;font color=#000000&gt;&amp;nbsp;&lt;/font&gt;
&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;public&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;override&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: blue"&gt;void&lt;/span&gt;&lt;font color=#000000&gt; Save()
{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: gray"&gt;//create
a guid for this viewstate&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: teal"&gt;Guid&lt;/span&gt;&lt;font color=#000000&gt; guid
= &lt;/font&gt;&lt;span style="COLOR: teal"&gt;Guid&lt;/span&gt;&lt;font color=#000000&gt;.NewGuid();&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;
&lt;o:p&gt;
&lt;font color=#000000&gt;&amp;nbsp;&lt;/font&gt;
&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: gray"&gt;//serialize
the states into a temp file&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;using&lt;/span&gt;&lt;font color=#000000&gt; (&lt;/font&gt;&lt;span style="COLOR: teal"&gt;TextWriter&lt;/span&gt;&lt;font color=#000000&gt; writer
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;new&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: teal"&gt;StreamWriter&lt;/span&gt;&lt;font color=#000000&gt;(CreateOfflineViewStateFilePath(guid)))
{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 3"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: teal"&gt;Pair&lt;/span&gt;&lt;font color=#000000&gt; pair
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;new&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: teal"&gt;Pair&lt;/span&gt;&lt;font color=#000000&gt;(&lt;/font&gt;&lt;span style="COLOR: blue"&gt;base&lt;/span&gt;&lt;font color=#000000&gt;.ViewState, &lt;/font&gt;&lt;span style="COLOR: blue"&gt;base&lt;/span&gt;&lt;font color=#000000&gt;.ControlState);&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;writer.Write(&lt;/font&gt;&lt;span style="COLOR: blue"&gt;this&lt;/span&gt;&lt;font color=#000000&gt;.StateFormatter.Serialize(pair));&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: gray"&gt;//trick
the normal system into thinking all it needs to save is the guid&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;base&lt;/span&gt;&lt;font color=#000000&gt;.ControlState
= guid;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;base&lt;/span&gt;&lt;font color=#000000&gt;.ViewState
= &lt;/font&gt;&lt;span style="COLOR: blue"&gt;null&lt;/span&gt;&lt;font color=#000000&gt;;&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;base&lt;/span&gt;&lt;font color=#000000&gt;.Save();&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;
&lt;o:p&gt;
&lt;font color=#000000&gt;&amp;nbsp;&lt;/font&gt;
&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;string&lt;/span&gt;&lt;font color=#000000&gt; CreateOfflineViewStateFilePath(&lt;/font&gt;&lt;span style="COLOR: teal"&gt;Guid&lt;/span&gt;&lt;font color=#000000&gt; guid)
{&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: gray"&gt;//TODO:
put these files whereever you like&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;return&lt;/span&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;span style="COLOR: teal"&gt;Path&lt;/span&gt;&lt;font color=#000000&gt;.Combine(&lt;/font&gt;&lt;span style="COLOR: teal"&gt;Path&lt;/span&gt;&lt;font color=#000000&gt;.GetTempPath(), &lt;/font&gt;&lt;span style="COLOR: blue"&gt;string&lt;/span&gt;&lt;font color=#000000&gt;.Format(&lt;/font&gt;&lt;span style="COLOR: maroon"&gt;"{0}.viewstate"&lt;/span&gt;&lt;font color=#000000&gt;,
guid));&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;
&lt;o:p&gt;
&lt;font color=#000000&gt;&amp;nbsp;&lt;/font&gt;
&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;
&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;font color=#000000&gt;}&lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
So, we immediately see that it's much shorter.&amp;nbsp; This is because ASP.net uses
a mechanism very similar to my 1.1 solution, so alot of the plumbing is&amp;nbsp;built-in.&amp;nbsp;The
only thing you need to do to use it is override the PageStatePersister property on
Page and return one of these.&amp;nbsp;Again, we're piggybacking on the "hidden field"
persistence mechanism and using that to store our Guid for the request.&amp;nbsp; Not
much different, and I'm pretty happy to say that converting to this model from my
old is very simple.
&lt;/p&gt;
&lt;p&gt;
Another interesting idea would be to leave&amp;nbsp;the ControlState in the hidden field,
and only store the ViewState in the file. it would be a simple change that I'll leave
as an exercise to you.&amp;nbsp; Then, you could be very aggresive about purging old or
large files without worrying about breaking anything (provided of course that you've
made your controls tolerant to such a method).
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=50f8adeb-bef6-43c5-a48e-81575ac99a4a" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,50f8adeb-bef6-43c5-a48e-81575ac99a4a.aspx</comments>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=03e6391b-e256-4a31-a486-52254d402b74</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,03e6391b-e256-4a31-a486-52254d402b74.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,03e6391b-e256-4a31-a486-52254d402b74.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=03e6391b-e256-4a31-a486-52254d402b74</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
My friend <a href="http://www.marklio.com/marklio/ct.ashx?id=03e6391b-e256-4a31-a486-52254d402b74&amp;url=http%3a%2f%2fwww.flatlandmedia.com%2fflatlander%2fSyndicationService.asmx%2fGetRss">Peter</a> and
I often use Remote Assistance to collaborate on projects.  He and I were doing
some things today in Visual Studio, and while I was watching, a beautiful window appeared
that showed the open files and windows and such, complete with appropriate icons.
"Whoa!", I said, "What was that?!"  "What", he replied, "this?"  The window
re-appeared.  Turns out, it was the Ctrl-Tab window.  For some reason, I
never even thought of using it to browse the open windows. I always assumed I
had to navigate the frightful tabbed interface, which just might actually be usable
with that little trick.
</p>
        <p>
I felt better when I typed in a type name and Intellisense didn't recongnize it. 
A quick right-click-&gt;Resolve instantly added the appropriate using statement. 
Peter hadn't seen that feature.  Although I guess Ctrl-Tab's been a standard
for much longer than Resolve.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=03e6391b-e256-4a31-a486-52254d402b74" />
      </body>
      <title>Discovering new Visual Studio features while collaborating</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,03e6391b-e256-4a31-a486-52254d402b74.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,03e6391b-e256-4a31-a486-52254d402b74.aspx</link>
      <pubDate>Sat, 20 Aug 2005 19:26:33 GMT</pubDate>
      <description>&lt;p&gt;
My friend &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=03e6391b-e256-4a31-a486-52254d402b74&amp;amp;url=http%3a%2f%2fwww.flatlandmedia.com%2fflatlander%2fSyndicationService.asmx%2fGetRss"&gt;Peter&lt;/a&gt; and
I often use Remote Assistance to collaborate on projects.&amp;nbsp; He and I were doing
some things today in Visual Studio, and while I was watching, a beautiful window appeared
that showed the open files and windows and such, complete with appropriate icons.
"Whoa!", I said, "What was that?!"&amp;nbsp; "What", he replied, "this?"&amp;nbsp; The window
re-appeared.&amp;nbsp; Turns out, it was the Ctrl-Tab window.&amp;nbsp; For some reason, I
never even thought of using it to browse the open windows.&amp;nbsp;I always assumed I
had to navigate the frightful tabbed interface, which just might actually be usable
with that little trick.
&lt;/p&gt;
&lt;p&gt;
I felt better when I typed in a type name and Intellisense didn't recongnize it.&amp;nbsp;
A quick right-click-&amp;gt;Resolve instantly added the appropriate using statement.&amp;nbsp;
Peter hadn't seen that feature.&amp;nbsp; Although I guess Ctrl-Tab's been a standard
for much longer than Resolve.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=03e6391b-e256-4a31-a486-52254d402b74" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,03e6391b-e256-4a31-a486-52254d402b74.aspx</comments>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=732f315c-fe81-4ed1-bb94-ec980f7eba9a</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,732f315c-fe81-4ed1-bb94-ec980f7eba9a.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,732f315c-fe81-4ed1-bb94-ec980f7eba9a.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=732f315c-fe81-4ed1-bb94-ec980f7eba9a</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
This past week, I've found myself writing alot of methods with the following pattern:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
IEnumerable&lt;T&gt; DoSomething(IEnumerable&lt;T&gt; stream);
</p>
        </blockquote>
        <p>
Then I use C#'s wonderful new iterator syntax to manipulate the stream, or simply
intercept and process the data. I've found this wonderfully useful for alot of the
statistical type algorithms that I implement for our project. It's been especially
cool to combine this with a bit of reflection for creating "dynamic filters" based
on user input. All of a sudden, all your algorithms are incredibly flexible with very
little effort.
</p>
        <p>
The beauty of this pattern is that it can be chained. Obviously, there is a practical
limit here, but I've found it extremely useful and I thought I'd share it for those
who haven't stumbled across this concept before.
</p>
        <p>
Now, if we could only create iterators using anonymous delegates, then I would proceed
to drown in my own drool.
</p>
        <p>
[UPDATE] fixed title grammar. Sorry if that pops it back up in your aggregators, RSS
readers.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=732f315c-fe81-4ed1-bb94-ec980f7eba9a" />
      </body>
      <title>Chaining object streams with C# iterators</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,732f315c-fe81-4ed1-bb94-ec980f7eba9a.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,732f315c-fe81-4ed1-bb94-ec980f7eba9a.aspx</link>
      <pubDate>Thu, 18 Aug 2005 20:29:34 GMT</pubDate>
      <description>&lt;p&gt;
This past week, I've found myself writing alot of methods with the following pattern:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
IEnumerable&amp;lt;T&amp;gt; DoSomething(IEnumerable&amp;lt;T&amp;gt; stream);
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Then I use C#'s wonderful new iterator syntax to manipulate the stream, or simply
intercept and process the data. I've found this wonderfully useful for alot of the
statistical type algorithms that I implement for our project. It's been especially
cool to combine this with a bit of reflection for creating "dynamic filters" based
on user input. All of a sudden, all your algorithms are incredibly flexible with very
little effort.
&lt;/p&gt;
&lt;p&gt;
The beauty of this pattern is that it can be chained. Obviously, there is a practical
limit here, but I've found it extremely useful and I thought I'd share it for those
who haven't stumbled across this concept before.
&lt;/p&gt;
&lt;p&gt;
Now, if we could only create iterators using anonymous delegates, then I would proceed
to drown in my own drool.
&lt;/p&gt;
&lt;p&gt;
[UPDATE] fixed title grammar. Sorry if that pops it back up in your aggregators, RSS
readers.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=732f315c-fe81-4ed1-bb94-ec980f7eba9a" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,732f315c-fe81-4ed1-bb94-ec980f7eba9a.aspx</comments>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=ccae93c7-cb00-4697-acce-6444579c1184</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,ccae93c7-cb00-4697-acce-6444579c1184.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,ccae93c7-cb00-4697-acce-6444579c1184.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=ccae93c7-cb00-4697-acce-6444579c1184</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I blogged a few days ago about a <a href="http://www.marklio.com/marklio/ct.ashx?id=ccae93c7-cb00-4697-acce-6444579c1184&amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2ce607db75-50f2-4010-aee0-36dee1c93f63.aspx">crazy
problem I had with garbage collection in ASP.net under 2.0</a>.  I finally tracked
the problem down to Array.Sort.  I created a framework for working with large
sets of data in a dynamic way.  This allows us to group data and do other complex
statistical things based on fairly open-ended user input, rather than having
to write special case code for each scenario.  It uses some reflection to be
able to drill into objects.  When sorting, we pass in a dynamic IComparer that
can drill into each object and do dynamic comparisons.  Unfortunately, many of
our algorithms were dependent on sorting the data first.  This was causing a
huge number of allocations due to drilling in and boxing lots of value types. 
And, the nature of the sort causes that to happen multiple times per item.
</p>
        <p>
Under 1.1, we took the hit on memory.  It didn't take that long, and it was soon
collected.  Under 2.0, the GC seems to recognize this allocation pattern early
and proactively begins collecting aggresively.  The problem seems to be that
this slows down the sort tremendously, to the point where it essentially comes to
a halt.  After a long time, you get a bizarre looking exception about a failed
sort from deep in the framework.
</p>
        <p>
What I can't figure out is, during all this time, there's still plenty of memory,
and activity on other requests is not impacted horribly.
</p>
        <p>
Well, I took a long hard look at some of the operations, and re-implemented them with
a hashing strategy rather than relying on a sort.  As it turns out, for most
cases, this is much more efficient.  Long story short, overnight stress testing
turned up with clean results this morning.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=ccae93c7-cb00-4697-acce-6444579c1184" />
      </body>
      <title>Update on my crazy garbage collection issue</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,ccae93c7-cb00-4697-acce-6444579c1184.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,ccae93c7-cb00-4697-acce-6444579c1184.aspx</link>
      <pubDate>Wed, 17 Aug 2005 14:37:49 GMT</pubDate>
      <description>&lt;p&gt;
I blogged a few days ago about a &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=ccae93c7-cb00-4697-acce-6444579c1184&amp;amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2ce607db75-50f2-4010-aee0-36dee1c93f63.aspx"&gt;crazy
problem I had with garbage collection in ASP.net under 2.0&lt;/a&gt;.&amp;nbsp; I finally tracked
the problem down to Array.Sort.&amp;nbsp; I created a framework for working with large
sets of data in a dynamic way.&amp;nbsp; This allows us to group data and do other complex
statistical&amp;nbsp;things&amp;nbsp;based on fairly open-ended user input, rather than having
to write special case code for each scenario.&amp;nbsp; It uses some reflection to be
able to drill into objects.&amp;nbsp; When sorting, we pass in a dynamic IComparer that
can drill into each object and do dynamic comparisons.&amp;nbsp; Unfortunately, many of
our algorithms were dependent on sorting the data first.&amp;nbsp; This was causing a
huge number of allocations due to drilling in&amp;nbsp;and boxing lots of value types.&amp;nbsp;
And, the nature of the sort causes that to happen multiple times per item.
&lt;/p&gt;
&lt;p&gt;
Under 1.1, we took the hit on memory.&amp;nbsp; It didn't take that long, and it was soon
collected.&amp;nbsp; Under 2.0, the GC seems to recognize this allocation pattern early
and proactively begins collecting aggresively.&amp;nbsp; The problem seems to be that
this slows down the sort tremendously, to the point where it essentially comes to
a halt.&amp;nbsp; After a long time, you get a bizarre looking exception about a failed
sort from deep in the framework.
&lt;/p&gt;
&lt;p&gt;
What I can't figure out is, during all this time, there's still plenty of memory,
and&amp;nbsp;activity on other requests is not impacted horribly.
&lt;/p&gt;
&lt;p&gt;
Well, I took a long hard look at some of the operations, and re-implemented them with
a hashing strategy rather than relying on a sort.&amp;nbsp; As it turns out, for most
cases, this is much more efficient.&amp;nbsp; Long story short, overnight stress testing
turned up with clean results this morning.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=ccae93c7-cb00-4697-acce-6444579c1184" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,ccae93c7-cb00-4697-acce-6444579c1184.aspx</comments>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=9e4b07ee-4816-4e72-ab8c-a0e4f821615b</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,9e4b07ee-4816-4e72-ab8c-a0e4f821615b.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,9e4b07ee-4816-4e72-ab8c-a0e4f821615b.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=9e4b07ee-4816-4e72-ab8c-a0e4f821615b</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
This is awesome.  <a href="http://www.marklio.com/marklio/ct.ashx?id=9e4b07ee-4816-4e72-ab8c-a0e4f821615b&amp;url=http%3a%2f%2fwww.bluebytesoftware.com%2fblog%2fPermaLink.aspx%3fguid%3d104175ad-2448-4607-bd12-4b02f877fe29">Joe
Duffy reveals </a>what I had suspected.  A change to the CLR that will fix the
issues I've <a href="http://www.marklio.com/marklio/ct.ashx?id=9e4b07ee-4816-4e72-ab8c-a0e4f821615b&amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2cd77e7612-7dbc-4555-9ae6-e1a607b5740e.aspx">previously
discussed</a> about nullable types in version 2.0!  From his blog:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font color="#a9a9a9">The core of this change is that the IL <em>box </em>instruction
has been modified to recognize Nullable&lt;T&gt;s. For non-Nullables, behavior remains
the same; but upon seeing one, it inspects its HasValue property. If HasValue
is true, box peeks inside the structure, extracts the T value, and boxes that instead;
otherwise, box simply leaves behind a null reference. Obviously, <em>unbox </em>has
also been changed to allow nulls to be unboxed back into Nullable&lt;T&gt; structures.
This had a rippling effect in the CLR codebase and also required changes to late-bound
semantics to mimic the static case. </font>
          </p>
        </blockquote>
        <p>
This is fantastic, and reveals just how strong Microsoft's commitment is to the development
community.  I gave my feedback on this before.  I felt it was a problem
that aware developers could understand and live with, but I felt that novice developers
would struggle with it, and ultimately it would make the feature, and the platform
less understandable and approachable.
</p>
        <p>
As you can tell from my earlier post, I had pretty much decided that MS would be unable
to fix it at this late stage in the game, and that would be a shame.  But, thanks
to some good decision making, they've done it.  Also, the solution was quite
similar to my suggestion, I'm happy to say.
</p>
        <p>
Be sure to follow through and read <a href="http://www.marklio.com/marklio/ct.ashx?id=9e4b07ee-4816-4e72-ab8c-a0e4f821615b&amp;url=http%3a%2f%2fblogs.msdn.com%2fsomasegar%2farchive%2f2005%2f08%2f11%2f450640.aspx">Somasegar's
post</a> on the subject.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=9e4b07ee-4816-4e72-ab8c-a0e4f821615b" />
      </body>
      <title>Issues with nullable types fixed!!!!</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,9e4b07ee-4816-4e72-ab8c-a0e4f821615b.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,9e4b07ee-4816-4e72-ab8c-a0e4f821615b.aspx</link>
      <pubDate>Fri, 12 Aug 2005 18:04:23 GMT</pubDate>
      <description>&lt;p&gt;
This is awesome.&amp;nbsp; &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=9e4b07ee-4816-4e72-ab8c-a0e4f821615b&amp;amp;url=http%3a%2f%2fwww.bluebytesoftware.com%2fblog%2fPermaLink.aspx%3fguid%3d104175ad-2448-4607-bd12-4b02f877fe29"&gt;Joe
Duffy reveals &lt;/a&gt;what I had suspected.&amp;nbsp; A change to the CLR that will fix the
issues I've &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=9e4b07ee-4816-4e72-ab8c-a0e4f821615b&amp;amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2cd77e7612-7dbc-4555-9ae6-e1a607b5740e.aspx"&gt;previously
discussed&lt;/a&gt; about nullable types in version 2.0!&amp;nbsp; From his blog:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;font color=#a9a9a9&gt;The core of this change is that the IL &lt;em&gt;box &lt;/em&gt;instruction
has been modified to recognize Nullable&amp;lt;T&amp;gt;s. For non-Nullables, behavior remains
the same; but&amp;nbsp;upon seeing one, it inspects its HasValue property. If HasValue
is true, box peeks inside the structure, extracts the T value, and boxes that instead;
otherwise, box simply leaves behind a null reference. Obviously, &lt;em&gt;unbox &lt;/em&gt;has
also been changed to allow nulls to be unboxed back into Nullable&amp;lt;T&amp;gt; structures.
This had a rippling effect in the CLR codebase&amp;nbsp;and also required changes to late-bound
semantics to mimic the static case. &lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
This is fantastic, and reveals just how strong Microsoft's commitment is to the development
community.&amp;nbsp; I gave my feedback on this before.&amp;nbsp; I felt it was a problem
that aware developers could understand and live with, but I felt that novice developers
would struggle with it, and ultimately it would make the feature, and the platform
less understandable and approachable.
&lt;/p&gt;
&lt;p&gt;
As you can tell from my earlier post, I had pretty much decided that MS would be unable
to fix it at this late stage in the game, and that would be a shame.&amp;nbsp; But, thanks
to some good decision making, they've done it.&amp;nbsp; Also, the solution was quite
similar to my suggestion, I'm happy to say.
&lt;/p&gt;
&lt;p&gt;
Be sure to follow through and read &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=9e4b07ee-4816-4e72-ab8c-a0e4f821615b&amp;amp;url=http%3a%2f%2fblogs.msdn.com%2fsomasegar%2farchive%2f2005%2f08%2f11%2f450640.aspx"&gt;Somasegar's
post&lt;/a&gt; on the subject.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=9e4b07ee-4816-4e72-ab8c-a0e4f821615b" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,9e4b07ee-4816-4e72-ab8c-a0e4f821615b.aspx</comments>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=54046378-97c4-4635-92bc-e6e8733a0ad6</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,54046378-97c4-4635-92bc-e6e8733a0ad6.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,54046378-97c4-4635-92bc-e6e8733a0ad6.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=54046378-97c4-4635-92bc-e6e8733a0ad6</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
As if I didn't have enough fun stuff to play with, the first Windows Vista beta was
released last week.  I put it on my little laptop first, where it ran very well,
but I was disappointed that the new visuals didn't run on the crappy video card it
has.  So, last night, I put the 64-bit version on my PC, which has a recent ATI
card on it.  Everything runs great on it and it's quite beautiful.  Both
installs I've done have been utterly trouble free.  It brought back pleasant
memories of installing the 95 beta and waiting with anticipation through the "Starting
windows for the first time" screen, which always reminded me of that cereal commercial..."taste
it again... for the first time".
</p>
        <p>
This evening, I'll be putting my apps back on the PC, so we'll see if I run across
any problems there.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=54046378-97c4-4635-92bc-e6e8733a0ad6" />
      </body>
      <title>Windows Vista</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,54046378-97c4-4635-92bc-e6e8733a0ad6.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,54046378-97c4-4635-92bc-e6e8733a0ad6.aspx</link>
      <pubDate>Mon, 01 Aug 2005 18:06:07 GMT</pubDate>
      <description>&lt;p&gt;
As if I didn't have enough fun stuff to play with, the first Windows Vista beta was
released last week.&amp;nbsp; I put it on my little laptop first, where it ran very well,
but I was disappointed that the new visuals didn't run on the crappy video card it
has.&amp;nbsp; So, last night, I put the 64-bit version on my PC, which has a recent ATI
card on it.&amp;nbsp; Everything runs great on it and it's quite beautiful.&amp;nbsp; Both
installs I've done have been utterly trouble free.&amp;nbsp; It brought back pleasant
memories of installing the 95 beta and waiting with anticipation through the "Starting
windows for the first time" screen, which always reminded me of that cereal commercial..."taste
it again... for the first time".
&lt;/p&gt;
&lt;p&gt;
This evening, I'll be putting my apps back on the PC, so we'll see if I run across
any problems there.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=54046378-97c4-4635-92bc-e6e8733a0ad6" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,54046378-97c4-4635-92bc-e6e8733a0ad6.aspx</comments>
      <category>Fun</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=30969330-c5e0-428a-ba68-3562bfb12a67</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,30969330-c5e0-428a-ba68-3562bfb12a67.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,30969330-c5e0-428a-ba68-3562bfb12a67.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=30969330-c5e0-428a-ba68-3562bfb12a67</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Sorry for the sparse updates.  I've been head-down on quite a few projects recently,
so most of my ramblings have taken the form of internal blog entries and emails. 
For the last several months, I've been pushing my co-workers to think about migrating
to Whidbey (The next version of Microsoft's .Net Framework, the CLR, whatever you
want to call it) sooner than later.  Most people know I'm an early adopter of
new technology, and always take my suggestions as the ravings of someone infatuated
over new things.  However, we're finally moving that direction for one of our
biggest tools as a result of some performance optimizations I was able to do with
new features provided in 2.0 (namely generics, iterators, and some new asp.net goodness). 
The performance opportunities alone are return enough for the investment.
</p>
        <p>
          <a href="http://www.marklio.com/marklio/ct.ashx?id=30969330-c5e0-428a-ba68-3562bfb12a67&amp;url=http%3a%2f%2fblogs.msdn.com%2fricom%2farchive%2f2005%2f07%2f27%2f444136.aspx">Rico
shares with us an overview of these opportunities</a>, and it's a good enough list
that even a manager can see the benefits, many of them handed to you without any additional
work.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=30969330-c5e0-428a-ba68-3562bfb12a67" />
      </body>
      <title>Logical Reasoning for moving to Whidbey</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,30969330-c5e0-428a-ba68-3562bfb12a67.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,30969330-c5e0-428a-ba68-3562bfb12a67.aspx</link>
      <pubDate>Thu, 28 Jul 2005 14:53:41 GMT</pubDate>
      <description>&lt;p&gt;
Sorry for the sparse updates.&amp;nbsp; I've been head-down on quite a few projects recently,
so most of my ramblings have taken the form of internal blog entries and emails.&amp;nbsp;
For the last several months, I've been pushing my co-workers to think about migrating
to Whidbey (The next version of Microsoft's .Net Framework, the CLR, whatever you
want to call it) sooner than later.&amp;nbsp; Most people know I'm an early adopter of
new technology, and always take my suggestions as the ravings of someone infatuated
over new things.&amp;nbsp; However, we're finally moving that direction for one of our
biggest tools as a result of some performance optimizations I was able to do with
new features provided in 2.0 (namely generics, iterators, and some new asp.net goodness).&amp;nbsp;
The performance opportunities alone are return enough for the investment.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.marklio.com/marklio/ct.ashx?id=30969330-c5e0-428a-ba68-3562bfb12a67&amp;amp;url=http%3a%2f%2fblogs.msdn.com%2fricom%2farchive%2f2005%2f07%2f27%2f444136.aspx"&gt;Rico
shares with us an overview of these opportunities&lt;/a&gt;, and it's a good enough list
that even a manager can see the benefits, many of them handed to you without any additional
work.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=30969330-c5e0-428a-ba68-3562bfb12a67" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,30969330-c5e0-428a-ba68-3562bfb12a67.aspx</comments>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=d532e590-84ee-4069-8260-719c4c3fbc1f</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,d532e590-84ee-4069-8260-719c4c3fbc1f.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,d532e590-84ee-4069-8260-719c4c3fbc1f.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=d532e590-84ee-4069-8260-719c4c3fbc1f</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
A large part of my time at work recently has been addressing scalability issues in
some applications.  Most of these stem from poor use of memory.  Most of
these applications were proof of concept that made their way into production code
for whatever reason.  More and more we identify problems and when we identify
them to the developer, this is the typical exchange:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
Me: You're taking too much memory here by using type Xxxxx when you could have gotten
by with type Yyyyy
</p>
          <p>
Dev: I have to use type Xxxxx, that's what the data is.
</p>
        </blockquote>
        <p dir="ltr">
Sometimes, you just have to take a step back and look at your bytes.  Sometimes,
you need a profiler, but sometimes you can just do some math.
</p>
        <p dir="ltr">
For example, if I have an array of dates that correspond to events, a logical
choice for a datatype is System.DateTime.  However, if you've got millions of
events, System.DateTime is relatively expensive.  Especially if you consider
that your event times only have resolution down to the nearest minute and only represent
times within the last several weeks.  The range, or domain of DateTime (ticks
since the epoch) is overkill for your circumstances. You may have been able to
get away with UInt16, which would have been 2 bytes instead of 8, which is a huge
reduction. (Provided that you've shown this array of DateTime to be a significant
part of your memory consumption.)
</p>
        <p dir="ltr">
I'm sure there is some official name for this, but I'll refer to it as "constrained
domain", where you know something about your circumstances or usage that
allows you to reduce the range or domain of a concept in order to store it as something
smaller to improve memory consumption.  Remember, just because a big, rich datatype
makes things easier, matches a db schema, or is named the same as the concept
you need to store, doesn't mean it's a good match for your scenario.
</p>
        <p dir="ltr">
There are, of course, other considerations to make.  The Y2k problems were the
direct result of taking this concept to the extreme (of course resources were in much
shorter supply then than they are today).
</p>
        <p dir="ltr">
So, when you are looking for places to trim your memory usage, look for places where
you can constrain the domain of a concept and store it in fewer bytes.  Also,
if you're in CLR-land when you do this, look for boxing value types.  Remember,
bytes in a System.Collections.ArrayList take up 5 bytes each, not 1. (9 bytes in 64-bit
land) (Yeah generics)
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=d532e590-84ee-4069-8260-719c4c3fbc1f" />
      </body>
      <title>Using "constrained domain" information to reduce memory consumption</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,d532e590-84ee-4069-8260-719c4c3fbc1f.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,d532e590-84ee-4069-8260-719c4c3fbc1f.aspx</link>
      <pubDate>Tue, 28 Jun 2005 16:17:05 GMT</pubDate>
      <description>&lt;p&gt;
A large part of my time at work recently has been addressing scalability issues in
some applications.&amp;nbsp; Most of these stem from poor use of memory.&amp;nbsp; Most of
these applications were proof of concept that made their way into production code
for whatever reason.&amp;nbsp; More and more we identify problems and when we identify
them to the developer, this is the typical exchange:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
Me: You're taking too much memory here by using type Xxxxx when you could have gotten
by with type Yyyyy
&lt;/p&gt;
&lt;p&gt;
Dev: I have to use type Xxxxx, that's what the data is.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
Sometimes, you just have to take a step back and look at your bytes.&amp;nbsp;&amp;nbsp;Sometimes,
you need&amp;nbsp;a profiler, but sometimes you can just do some math.
&lt;/p&gt;
&lt;p dir=ltr&gt;
For example,&amp;nbsp;if I have an array of dates that correspond to events, a logical
choice for a datatype is System.DateTime.&amp;nbsp; However, if you've got millions of
events, System.DateTime is relatively expensive.&amp;nbsp; Especially if you consider
that your event times only have resolution down to the nearest minute and only represent
times within the last several weeks.&amp;nbsp; The range, or domain of DateTime (ticks
since the epoch)&amp;nbsp;is overkill for your circumstances. You may have been able to
get away with UInt16, which would have been 2 bytes instead of 8, which is a huge
reduction. (Provided that you've shown this array of DateTime to be a significant
part of your memory consumption.)
&lt;/p&gt;
&lt;p dir=ltr&gt;
I'm sure there is some official name for this, but I'll refer to it as "constrained
domain",&amp;nbsp;where you know something about your circumstances or usage&amp;nbsp;that
allows you to reduce the range or domain of a concept in order to store it as something
smaller to improve memory consumption.&amp;nbsp; Remember, just because a big, rich datatype
makes things easier, matches a db schema, or is named the same as the&amp;nbsp;concept
you need to store, doesn't mean it's a good match for your scenario.
&lt;/p&gt;
&lt;p dir=ltr&gt;
There are, of course, other considerations to make.&amp;nbsp; The Y2k problems were the
direct result of taking this concept to the extreme (of course resources were in much
shorter supply then than they are today).
&lt;/p&gt;
&lt;p dir=ltr&gt;
So, when you are looking for places to trim your memory usage, look for places where
you can constrain the domain of a concept and store it in fewer bytes.&amp;nbsp; Also,
if you're in CLR-land when you do this, look for boxing value types.&amp;nbsp; Remember,
bytes in a System.Collections.ArrayList take up 5 bytes each, not 1. (9 bytes in 64-bit
land) (Yeah generics)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=d532e590-84ee-4069-8260-719c4c3fbc1f" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,d532e590-84ee-4069-8260-719c4c3fbc1f.aspx</comments>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=de1c560e-9f2f-43e3-830e-3e195fbebea5</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,de1c560e-9f2f-43e3-830e-3e195fbebea5.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,de1c560e-9f2f-43e3-830e-3e195fbebea5.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=de1c560e-9f2f-43e3-830e-3e195fbebea5</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Back last year, <a href="http://www.marklio.com/marklio/ct.ashx?id=de1c560e-9f2f-43e3-830e-3e195fbebea5&amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2cd348134e-cc21-4586-8535-6266753f3412.aspx">I
outlined a problem I had with calling Response.End from a thread other than the thread
that handled the request</a>.  It stemmed from a progress mechanism we had implemented
that had the ability to cancel long-running tasks when the user hit stop or closed
the browser.  As it turns out, that wasn't the whole story.
</p>
        <p>
We recently added a few reports where, the majority of the time, gathering the data
takes over a couple of minutes.  While doing memory and performance optimizations,
we noticed our worker process was recycling with the following message in the System
event log:
</p>
        <font size="1">
          <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
            <p>
A process serving application pool 'XXXXXXXXXX' terminated unexpectedly. The process
id was '####'. The process exit code was '0xff'.
</p>
          </blockquote>
        </font>
        <p>
Googling for this error doesn't do you much good since it could be caused by a variety
of reasons.  Most of the advice I came across wasn't well thought out and made
quite a few bad assumptions.  So we added some more debug logging and determined
that this was happening when our canceling mechanism kicked in when a user decided
they didn't really want to wait 5 minutes for the report.  I was greatly puzzled
by this since this feature had been tested thoroughly and had been running in production
for some time.  Looking back through the server logs, it was evident that it
had been happening all along, just not very often. We had just gotten the performance
on the vast majority of pages to be very good and it wasn't an issue.  The problem
only came to the surface when we added the report that always takes a while.
</p>
        <p>
Here's the problem.  If the handling thread is aborted, it causes a condition
that IIS considers to be bad and that forces the worker process to recycle. (presumably,
there is some communication that doesn't occur) This doesn't happen
when Response.End() is called because it passes a special exception as the exception
state to Thread.Abort.  The HttpApplication catches ThreadAbortException and
checks the ExceptionState.  If it is an HttpApplication.CancelModuleException,
it knows there was either a timeout, or Response.End() was called, and it cancels
the Thread.Abort by calling ResetAbort which allows the thread to continue running
at that point.  I thought that was pretty slick.
</p>
        <p>
When I was aborting the handling thread, I was on a different thread, so I had to
call Thread.Abort manually, so CancelModuleException was not being used, so the thread
was ending completely and causing the recycle.  Since HttpApplication.CancelModuleException
is internal (and rightly so) I could not simply use that mechanism.
</p>
        <p>
The good news is that the Unload event always happens (for all practical purposes),
even when the thread is being aborted.  So I added my own PageIsCancelling property
to our base class Page and check it, along with the current ThreadState in Unload,
and cancel any pending abort if the page is canceling.  So, the abort is contained
within the callstack of the page, and the thread stays alive and all is well. 
No more crazy recycling.
</p>
        <p>
As an aside, it seems this is aggravated by multiple processors, which might explain
how it passed testing on the dev's machine.  Although I don't have any proof
of this.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=de1c560e-9f2f-43e3-830e-3e195fbebea5" />
      </body>
      <title>Canceling long-running ASP.net requests from a separate thread</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,de1c560e-9f2f-43e3-830e-3e195fbebea5.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,de1c560e-9f2f-43e3-830e-3e195fbebea5.aspx</link>
      <pubDate>Fri, 10 Jun 2005 18:50:44 GMT</pubDate>
      <description>&lt;p&gt;
Back last year, &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=de1c560e-9f2f-43e3-830e-3e195fbebea5&amp;amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2cd348134e-cc21-4586-8535-6266753f3412.aspx"&gt;I
outlined a problem I had with calling Response.End from a thread other than the thread
that handled the request&lt;/a&gt;.&amp;nbsp; It stemmed from a progress mechanism we had implemented
that had the ability to cancel long-running tasks when the user hit stop or closed
the browser.&amp;nbsp; As it turns out, that wasn't the whole story.
&lt;/p&gt;
&lt;p&gt;
We recently added a few reports where, the majority of the time, gathering the data
takes over a couple of minutes.&amp;nbsp; While doing memory and performance optimizations,
we noticed our worker process was recycling with the following message in the System
event log:
&lt;/p&gt;
&lt;font size=1&gt; &lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
A process serving application pool 'XXXXXXXXXX' terminated unexpectedly. The process
id was '####'. The process exit code was '0xff'.
&lt;/p&gt;
&lt;/blockquote&gt;&lt;/font&gt; 
&lt;p&gt;
Googling for this error doesn't do you much good since it could be caused by a variety
of reasons.&amp;nbsp; Most of the advice I came across wasn't well thought out and made
quite a few bad assumptions.&amp;nbsp; So we added some more debug logging and determined
that this was happening when our canceling mechanism kicked in when a user decided
they didn't really want to wait 5 minutes for the report.&amp;nbsp; I was greatly puzzled
by this since this feature had been tested thoroughly and had been running in production
for some time.&amp;nbsp; Looking back through the server logs, it was evident that it
had been happening all along, just not very often. We had just gotten the performance
on the vast majority of pages to be very good and it wasn't an issue.&amp;nbsp; The problem
only came to the surface when we added the report that always takes a while.
&lt;/p&gt;
&lt;p&gt;
Here's the problem.&amp;nbsp; If the handling thread is aborted, it causes a condition
that IIS considers to be bad and that forces the worker process to recycle.&amp;nbsp;(presumably,
there is&amp;nbsp;some communication that doesn't&amp;nbsp;occur)&amp;nbsp;This doesn't happen
when Response.End() is called because it passes a special exception as the exception
state to Thread.Abort.&amp;nbsp; The HttpApplication catches ThreadAbortException and
checks the ExceptionState.&amp;nbsp; If it is an HttpApplication.CancelModuleException,
it knows there was either a timeout, or Response.End() was called, and it cancels
the Thread.Abort by calling ResetAbort which allows the thread to continue running
at that point.&amp;nbsp; I thought that was pretty slick.
&lt;/p&gt;
&lt;p&gt;
When I was aborting the handling thread, I was on a different thread, so I had to
call Thread.Abort manually, so CancelModuleException was not being used, so the thread
was ending completely and causing the recycle.&amp;nbsp; Since HttpApplication.CancelModuleException
is internal (and rightly so) I could not simply use that mechanism.
&lt;/p&gt;
&lt;p&gt;
The good news is that the Unload event always happens (for all practical purposes),
even when the thread is being aborted.&amp;nbsp; So I added my own PageIsCancelling property
to our base class Page and check it, along with the current ThreadState in Unload,
and cancel any pending abort if the page is canceling.&amp;nbsp; So, the abort is contained
within the callstack of the page, and the thread stays alive and all is well.&amp;nbsp;
No more crazy recycling.
&lt;/p&gt;
&lt;p&gt;
As an aside, it seems this is aggravated by multiple processors, which might explain
how it passed testing on the dev's machine.&amp;nbsp; Although I don't have any proof
of this.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=de1c560e-9f2f-43e3-830e-3e195fbebea5" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,de1c560e-9f2f-43e3-830e-3e195fbebea5.aspx</comments>
      <category>Crazy stuff</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=d77e7612-7dbc-4555-9ae6-e1a607b5740e</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,d77e7612-7dbc-4555-9ae6-e1a607b5740e.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,d77e7612-7dbc-4555-9ae6-e1a607b5740e.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=d77e7612-7dbc-4555-9ae6-e1a607b5740e</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p xmlns="http://www.w3.org/1999/xhtml">
The generic Nullable type in Whidbey and the C# language features it supports are
great.  They've enabled me to eliminate gobs of code and simplify things incredibly. But, <a href="http://www.marklio.com/marklio/ct.ashx?id=d77e7612-7dbc-4555-9ae6-e1a607b5740e&amp;url=http%3a%2f%2fwww.bluebytesoftware.com%2fblog%2fPermaLink.aspx%3fguid%3d4c7fecc7-8554-49b3-b4fb-5ca323803d76"><font color="#355ea0">Joe
Duffy's latest request for feedback</font></a> on some of the "syntactic suger" on
this feature brings up some interesting points.  He shows us several different
equality tests against a nullable value type and asks if the results are intuitive. 
I suspect it's a loaded question, because they are not.  Someone with
a good understanding of the framework can fairly easily guess the outcome, but deep
down I think they would have to admit it's not ideal. 
</p>
        <p xmlns="http://www.w3.org/1999/xhtml">
What it boils down to is what is the purpose of the generic Nullable type.  I
originally viewed it as helping to code against scenarios where values can be null
like databases.  Without nullable value types, you frequently have to check to
see whether you're dealing with a null value, and carry around alot of state information,
and Nullable simply does that for you.  I think some of the designers of this
feature see it much more broadly as a concept to unify the type system in a more performant
way than simply being able to cast to object.  This requires some special
casing, as is evident by the special case for type parameter constraints on generic
types.  Specifying struct will not allow you to use a generic Nullable, despite
the fact that it <strong>is</strong> a value type.  The problem is that the special
casing stops short of completely abstracting the concepts. 
</p>
        <p xmlns="http://www.w3.org/1999/xhtml">
The problem can readily be seen in Joe's second two tests, boxing a valueless "int?",
and using the equality operator "==" against a generic argument that is instantiated
as "int?" and has no value.  Both do the opposite of what you might expect if
you don't think through it first.  Both <strong>do not</strong> equate to null. 
</p>
        <p xmlns="http://www.w3.org/1999/xhtml">
I pondered this for quite a while before deciding how bad this was (and I'm still
not exactly sure).  For me, this is no problem since I understand the issues
at work.  For the future of the language, the outcome is not so clear. 
The real question is, "Is a value-less value type different from a null reference?" 
I don't think it should be.  If you cast a null string reference to object, does
it retain its identity as a string? No. Can you cast it back to a string reference?
Yes. So, should there be a difference in behavior with nullables? I'll let you
decide.  Then there is the issue of how (and if) to effectively fix it. 
Adding a conversion from Nullable to object that makes it a null reference instead
of a boxed value type might do it, at least for the boxing scenario.  That's
probably a pretty naive solution.  I haven't really thought that through. 
For the generic situation, Nullable seems to be already special cased to some degree. 
It doesn't seem like it would be too much of a stretch to generate appropriate code
for Nullable.  The big problem here is that since this happens at JIT time, it's
no longer a C# feature. Unfortunately, it's likely too late to address the issue in
the in any real way, and that will likely set too much precedence to change it in
the future if a solution could be reached.  Perhaps some FxCop rules could find
these types of situations and at least flag them so they could be looked at more closely. 
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=d77e7612-7dbc-4555-9ae6-e1a607b5740e" />
      </body>
      <title>Issues with Nullable Value Types</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,d77e7612-7dbc-4555-9ae6-e1a607b5740e.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,d77e7612-7dbc-4555-9ae6-e1a607b5740e.aspx</link>
      <pubDate>Tue, 17 May 2005 20:43:10 GMT</pubDate>
      <description>&lt;p xmlns="http://www.w3.org/1999/xhtml"&gt;
The generic Nullable type in Whidbey and the C# language features it supports are
great.&amp;nbsp; They've enabled me to eliminate gobs of code and simplify things incredibly.&amp;nbsp;But, &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=d77e7612-7dbc-4555-9ae6-e1a607b5740e&amp;amp;url=http%3a%2f%2fwww.bluebytesoftware.com%2fblog%2fPermaLink.aspx%3fguid%3d4c7fecc7-8554-49b3-b4fb-5ca323803d76"&gt;&lt;font color=#355ea0&gt;Joe
Duffy's latest request for feedback&lt;/font&gt;&lt;/a&gt; on some of the "syntactic suger" on
this feature brings up some interesting points.&amp;nbsp; He shows us several different
equality tests against a nullable value type and asks if the results are intuitive.&amp;nbsp;
I suspect it's a loaded question, because&amp;nbsp;they are&amp;nbsp;not.&amp;nbsp; Someone with
a good understanding of the framework can fairly easily guess the outcome, but deep
down I think they would have to admit it's not ideal. 
&lt;/p&gt;
&lt;p xmlns="http://www.w3.org/1999/xhtml"&gt;
What it boils down to is what is the purpose of the generic Nullable type.&amp;nbsp; I
originally viewed it as helping to code against scenarios where values can be null
like databases.&amp;nbsp; Without nullable value types, you frequently have to check to
see whether you're dealing with a null value, and carry around alot of state information,
and Nullable simply does that for you.&amp;nbsp; I think some of the designers of this
feature see it much more broadly as a concept to unify the type system in a more performant
way than simply being able to cast to object.&amp;nbsp; This requires some&amp;nbsp;special
casing, as is evident by the special case for type parameter constraints on generic
types.&amp;nbsp; Specifying struct will not allow you to use a generic Nullable, despite
the fact that it &lt;strong&gt;is&lt;/strong&gt; a value type.&amp;nbsp; The problem is that the special
casing stops short of completely abstracting the concepts. 
&lt;/p&gt;
&lt;p xmlns="http://www.w3.org/1999/xhtml"&gt;
The problem can readily be seen in Joe's second two tests, boxing a valueless&amp;nbsp;"int?",
and using the equality operator "==" against a generic argument that is instantiated
as "int?" and has no value.&amp;nbsp; Both do the opposite of what you might expect if
you don't think through it first.&amp;nbsp; Both &lt;strong&gt;do not&lt;/strong&gt; equate to null. 
&lt;/p&gt;
&lt;p xmlns="http://www.w3.org/1999/xhtml"&gt;
I pondered this for quite a while before deciding how bad this was (and I'm still
not exactly sure).&amp;nbsp; For me, this is no problem since I understand the issues
at work.&amp;nbsp; For the future&amp;nbsp;of the language, the outcome is not so clear.&amp;nbsp;
The real question is, "Is a value-less value type different from a null reference?"&amp;nbsp;
I don't think it should be.&amp;nbsp; If you cast a null string reference to object, does
it retain its identity as a string? No. Can you cast it back to a string reference?
Yes. So, should there be a difference in behavior with nullables?&amp;nbsp;I'll let you
decide.&amp;nbsp; Then there is the issue of how (and if) to effectively fix it.&amp;nbsp;
Adding a conversion from Nullable to object that makes it a null reference instead
of a boxed value type might do it, at least for the boxing scenario.&amp;nbsp; That's
probably a pretty naive solution.&amp;nbsp; I haven't really thought that through.&amp;nbsp;
For the generic situation, Nullable seems to be already special cased to some degree.&amp;nbsp;
It doesn't seem like it would be too much of a stretch to generate appropriate code
for Nullable.&amp;nbsp; The big problem here is that since this happens at JIT time, it's
no longer a C# feature. Unfortunately, it's likely too late to address the issue in
the in any real way, and that will likely set too much precedence to change it in
the future if a solution could be reached.&amp;nbsp; Perhaps some FxCop rules could find
these types of situations and at least flag them so they could be looked at more closely. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=d77e7612-7dbc-4555-9ae6-e1a607b5740e" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,d77e7612-7dbc-4555-9ae6-e1a607b5740e.aspx</comments>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=598ab4e7-bbfa-446b-b4db-78645912b7e5</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,598ab4e7-bbfa-446b-b4db-78645912b7e5.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,598ab4e7-bbfa-446b-b4db-78645912b7e5.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=598ab4e7-bbfa-446b-b4db-78645912b7e5</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
We have a big configuration file that maps business logic concepts to their currently
used implementations so we can dynamically switch these out.  Under ASP.NET
1.0, all those implementations were in assemblies with "well-known" names (meaning
we know them deterministically before compile-time).  Some of the implementations
were in nested classes of user controls (we'll save the debate over whether that is
a good idea for another time).  This means that the ASP.NET compiler is now in
charge of them, which makes their names more difficult to discover.
</p>
        <p>
Luckily, there's someone looking out for us here.  The System.Web.Compilation
namespace has all kinds of goodies to help us out here, namely the <a href="http://www.marklio.com/marklio/ct.ashx?id=598ab4e7-bbfa-446b-b4db-78645912b7e5&amp;url=http%3a%2f%2fmsdn2.microsoft.com%2flibrary%2f5z4b6bw6(en-us%2cvs.80).aspx">BuildManager</a> class. 
It has a <a href="http://www.marklio.com/marklio/ct.ashx?id=598ab4e7-bbfa-446b-b4db-78645912b7e5&amp;url=http%3a%2f%2fmsdn2.microsoft.com%2flibrary%2fa0z5yws8(en-us%2cvs.80).aspx">GetType</a> overload
that at first glance appears to do exactly what we want, unfortunately it only seems
to work if the assembly in question has already been loaded.  This is not usually
the case when our configuration code runs the first time.  Instead, you can use
a combination of <a href="http://www.marklio.com/marklio/ct.ashx?id=598ab4e7-bbfa-446b-b4db-78645912b7e5&amp;url=http%3a%2f%2fmsdn2.microsoft.com%2flibrary%2f2wddaf89(en-us%2cvs.80).aspx">GetCompiledAssembly</a> and
good ol' Assembly.GetType.  So now, instead of knowing the assembly name, we
need to know the virtual path to the compiled control. So here's a snippet that does
generally what I want:
</p>
        <font size="2">
          <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
            <p>
            </p>
          </blockquote>
        </font>
        <font color="#0000ff" size="2">if</font>
        <font size="2"> (!</font>
        <font color="#008080" size="2">String</font>
        <font size="2">.IsNullOrEmpty(urlString))
{
<p>
    System.Reflection.
</p></font>
        <font color="#008080" size="2">Assembly</font>
        <font size="2"> assembly
= </font>
        <font color="#008080" size="2">BuildManager</font>
        <font size="2">.GetCompiledAssembly(urlString);
<p>
    theTypeIWant = assembly.GetType(typeString, 
</p></font>
        <font color="#0000ff" size="2">true</font>
        <font size="2">);
<p>
}
</p><p></p></font>
        <font color="#0000ff" size="2">else</font>
        <font size="2"> {
<p>
    theTypeIWant = 
</p></font>
        <font color="#008080" size="2">Type</font>
        <font size="2">.GetType(typeString, </font>
        <font color="#0000ff" size="2">true</font>
        <font size="2">);
<p>
}
</p><p>
So, for those types that reside under ASP.NET's control, I add the virtual path to
the configuration and leave out the assembly name, and use it's presence to determine
if the BuildManager needs to get involved.
</p><p>
Also notice the wonderful String.IsNullOrEmpty method.  Now, if there were only
some kind of operator I could use to be even lazier about that check.
</p></font>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=598ab4e7-bbfa-446b-b4db-78645912b7e5" />
      </body>
      <title>Resolving/Loading Types in ASP.NET 2.0</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,598ab4e7-bbfa-446b-b4db-78645912b7e5.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,598ab4e7-bbfa-446b-b4db-78645912b7e5.aspx</link>
      <pubDate>Mon, 02 May 2005 18:16:09 GMT</pubDate>
      <description>&lt;p&gt;
We have a big configuration file that maps business logic concepts to their currently
used&amp;nbsp;implementations so we can dynamically switch these out.&amp;nbsp; Under ASP.NET
1.0, all those implementations were in assemblies with "well-known" names (meaning
we know them deterministically&amp;nbsp;before compile-time).&amp;nbsp; Some of the implementations
were in nested classes of user controls (we'll save the debate over whether that is
a good idea for another time).&amp;nbsp; This means that the ASP.NET compiler is now in
charge of them, which makes their names more difficult to discover.
&lt;/p&gt;
&lt;p&gt;
Luckily, there's someone looking out for us here.&amp;nbsp; The System.Web.Compilation
namespace has all kinds of goodies to help us out here, namely the &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=598ab4e7-bbfa-446b-b4db-78645912b7e5&amp;amp;url=http%3a%2f%2fmsdn2.microsoft.com%2flibrary%2f5z4b6bw6(en-us%2cvs.80).aspx"&gt;BuildManager&lt;/a&gt; class.&amp;nbsp;
It has a &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=598ab4e7-bbfa-446b-b4db-78645912b7e5&amp;amp;url=http%3a%2f%2fmsdn2.microsoft.com%2flibrary%2fa0z5yws8(en-us%2cvs.80).aspx"&gt;GetType&lt;/a&gt; overload
that at first glance appears to do exactly what we want, unfortunately it only seems
to work if the assembly in question has already been loaded.&amp;nbsp; This is not usually
the case when our configuration code runs the first time.&amp;nbsp; Instead, you can use
a combination of &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=598ab4e7-bbfa-446b-b4db-78645912b7e5&amp;amp;url=http%3a%2f%2fmsdn2.microsoft.com%2flibrary%2f2wddaf89(en-us%2cvs.80).aspx"&gt;GetCompiledAssembly&lt;/a&gt; and
good ol' Assembly.GetType.&amp;nbsp; So now, instead of knowing the assembly name, we
need to know the virtual path to the compiled control. So here's a snippet that does
generally what I want:
&lt;/p&gt;
&lt;font size=2&gt; &lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;if&lt;/font&gt;&lt;font size=2&gt; (!&lt;/font&gt;&lt;font color=#008080 size=2&gt;String&lt;/font&gt;&lt;font size=2&gt;.IsNullOrEmpty(urlString))
{&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Reflection.
&lt;/font&gt;&lt;font color=#008080 size=2&gt;Assembly&lt;/font&gt;&lt;font size=2&gt; assembly = &lt;/font&gt;&lt;font color=#008080 size=2&gt;BuildManager&lt;/font&gt;&lt;font size=2&gt;.GetCompiledAssembly(urlString);&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;theTypeIWant&amp;nbsp;= assembly.GetType(typeString, 
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;true&lt;/font&gt;&lt;font size=2&gt;);&gt;
&lt;p&gt;
}
&lt;/p&gt;
&lt;p&gt;
&lt;/font&gt;&lt;font color=#0000ff size=2&gt;else&lt;/font&gt;&lt;font size=2&gt; {&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; theTypeIWant&amp;nbsp;= 
&lt;/font&gt;&lt;font color=#008080 size=2&gt;Type&lt;/font&gt;&lt;font size=2&gt;.GetType(typeString, &lt;/font&gt;&lt;font color=#0000ff size=2&gt;true&lt;/font&gt;&lt;font size=2&gt;);&gt;
&lt;p&gt;
}
&lt;/p&gt;
&gt; 
&lt;p&gt;
So, for those types that reside under ASP.NET's control, I add the virtual path to
the configuration and leave out the assembly name, and use it's presence to determine
if the BuildManager needs to get involved.
&lt;/p&gt;
&lt;p&gt;
Also notice the wonderful String.IsNullOrEmpty method.&amp;nbsp; Now, if there were only
some kind of operator I could use to be even lazier about that check.
&lt;/p&gt;
&lt;/font&gt;&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=598ab4e7-bbfa-446b-b4db-78645912b7e5" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,598ab4e7-bbfa-446b-b4db-78645912b7e5.aspx</comments>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=c18a6cb4-8f08-4d42-ab97-3d19cbddcea0</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,c18a6cb4-8f08-4d42-ab97-3d19cbddcea0.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,c18a6cb4-8f08-4d42-ab97-3d19cbddcea0.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=c18a6cb4-8f08-4d42-ab97-3d19cbddcea0</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
We're making the move to 64-bit at work, and one of the things that's annoying me
the most is all the 32-bit shell extensions that I rely on and didn't realize it. 
For example, we use <a href="http://www.marklio.com/marklio/ct.ashx?id=c18a6cb4-8f08-4d42-ab97-3d19cbddcea0&amp;url=http%3a%2f%2fsubversion.tigris.org%2f">Subversion</a> for
source control and use the excellent <a href="http://www.marklio.com/marklio/ct.ashx?id=c18a6cb4-8f08-4d42-ab97-3d19cbddcea0&amp;url=http%3a%2f%2ftortoisesvn.tigris.org%2f">TortoiseSVN</a> shell
extension to work with it from explorer.  Since it's a 32-bit extension, it doesn't
show up in the context menu.
</p>
        <p>
There are two workarounds I've found for using these 32-bit extensions.
</p>
        <ol>
          <li>
Use the 32-bit explorer.exe in the SysWow64 directory.  You have to have the
"Launch folder windows in a separate process" option turned on, otherwise it will
just see that explorer is already running and start a new 64-bit window instead of
a new 32-bit process.</li>
          <li>
Use 32-bit IE.  There's already a shortcut to it by default in the start menu. 
Just fire it up and navigate to the filesystem instead of a web page.  Voila!
32-bit extensions start showing up.  I like this method since I don't have to
have a bunch of explorer processes for each window.</li>
        </ol>
        <p>
There's probably a cleaner way of using the 32-bit explorer, but I haven't figured
it out yet.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=c18a6cb4-8f08-4d42-ab97-3d19cbddcea0" />
      </body>
      <title>Running 32-bit shell extensions in 64-bit Windows</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,c18a6cb4-8f08-4d42-ab97-3d19cbddcea0.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,c18a6cb4-8f08-4d42-ab97-3d19cbddcea0.aspx</link>
      <pubDate>Thu, 14 Apr 2005 18:42:18 GMT</pubDate>
      <description>&lt;p&gt;
We're making the move to 64-bit at work, and one of the things that's annoying me
the most is all the 32-bit shell extensions that I rely on and didn't realize it.&amp;nbsp;
For example, we use &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=c18a6cb4-8f08-4d42-ab97-3d19cbddcea0&amp;amp;url=http%3a%2f%2fsubversion.tigris.org%2f"&gt;Subversion&lt;/a&gt; for
source control and use the excellent &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=c18a6cb4-8f08-4d42-ab97-3d19cbddcea0&amp;amp;url=http%3a%2f%2ftortoisesvn.tigris.org%2f"&gt;TortoiseSVN&lt;/a&gt; shell
extension to work with it from explorer.&amp;nbsp; Since it's a 32-bit extension, it doesn't
show up in the context menu.
&lt;/p&gt;
&lt;p&gt;
There are two workarounds I've found for using these 32-bit extensions.
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Use the 32-bit explorer.exe in the SysWow64 directory.&amp;nbsp; You have to have the
"Launch folder windows in a separate process" option turned on, otherwise it will
just see that explorer is already running and start a new 64-bit window instead of
a new 32-bit process.&lt;/li&gt;
&lt;li&gt;
Use 32-bit IE.&amp;nbsp; There's already a shortcut to it by default in the start menu.&amp;nbsp;
Just fire it up and navigate to the filesystem instead of a web page.&amp;nbsp; Voila!
32-bit extensions start showing up.&amp;nbsp; I like this method since I don't have to
have a bunch of explorer processes for each window.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
There's probably a cleaner way of using the 32-bit explorer, but I haven't figured
it out yet.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=c18a6cb4-8f08-4d42-ab97-3d19cbddcea0" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,c18a6cb4-8f08-4d42-ab97-3d19cbddcea0.aspx</comments>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=3a89ecce-89a8-470e-a894-bc5cc86ce41d</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,3a89ecce-89a8-470e-a894-bc5cc86ce41d.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,3a89ecce-89a8-470e-a894-bc5cc86ce41d.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=3a89ecce-89a8-470e-a894-bc5cc86ce41d</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Last night, I completed my <a href="http://www.marklio.com/marklio/ct.ashx?id=3a89ecce-89a8-470e-a894-bc5cc86ce41d&amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2ce3601f31-231b-4a82-b5a7-1c31600ce25c.aspx">STDF
file parser that I started over the weekend</a>.  I'm pretty happy with it. 
I now fully support all of the version 4 spec.  It's written with the Feb. 2005
CTP of Whidbey.  It was primarily a good example of a "real world" application,
so I wanted to use it to try out some of the spiffy new features and see how they
might fit into an application that was not built for the sole purpose of showing them
off.
</p>
        <p>
I'm not entirely sure what I should do with it now that I've built it.  There's
not much non-commercial demand for something like that that I am aware of. I
might be persuaded to license it for use commercially once there is a "go live" license
for Whidbey.  I'm sure it will need some testing to work out issues.  I'll
probably build a viewer using it and use it at work to get the kinks out of it. 
Anyway, I thought it might be useful to capture how some of these features played
out in a real scenario.
</p>
        <p>
          <strong>Lightweight Code Generation</strong>
        </p>
        <p>
I used attributes to annotate my record classes in order to define the "on disk" layout
of the record.  I originally put the attributes on the properties of the record,
but decided to move them to the class level so that I could define the fields that
are only used for parsing, and not useful after that.  At runtime, I register
the record types with the parser, which uses lightweight code generation to generate
converters from unknown records to the concrete records.  If you're not familiar
with LCG, it is essentially Reflection.Emit without the overhead of a dynamic assembly,
module, or type.  If you're unfamiliar with Reflection.Emit, it is essentially
generating executable IL code on the fly, which has may benefits over generating C#
or some other language and running it through the compiler with CodeDOM or soemthing
else. (If you're not familiar with IL, then this entry is somewhat irrelevant) Having
dealt with assembly on lots of different instruction sets from 68000 to x86 to DSPs
and microcontrollers, I must say that working in IL is wonderful.  I was a bit
worried about the startup time for the parser, but it seems to happen very quickly. 
I'll need to experiment more to come up with the overhead of the dynamic code. 
Again, I was disappointed in the lack of debugging support in LCG.
</p>
        <p>
          <strong>Generics</strong>
        </p>
        <p>
Unfortunately, generics did not work into the equation near as much as I had hoped. 
I did find them very useful in places where I would normally pass a Type.  Now
I can have a much stronger contract on such methods using generic methods with constraints. 
I must say that I love the generic collections.  Working with strongly-typed
data without having to generate the classes is very nice.  I also like being
able to do a custom sort with an inline anonymous delegate with closure-type
semantics rather than have the overhead of a separate class with the code in a different
place.
</p>
        <p>
          <strong>Iterators</strong>
        </p>
        <p>
Iterators came into play in several places.  In the pull-based record parser,
it was simple to implement IEnumerable.  I believe it only took 3 or 4 lines
of code.
</p>
        <p>
          <strong>Delegate type inference</strong>
        </p>
        <p>
I don't remember what the official name of this feature is, but instead of having
to do something like SomeEvent += new EventHandler(SomeMethod), you can just do SomeEvent
+= SomeMethod.  This seems small, but I appreciated it quite a bit.
</p>
        <p>
          <strong>Visual Studio Enhancements</strong>
        </p>
        <p>
These were a very pleasant surprise.  I hadn't thought about the exercise as
testing the VS enhancements.  The snippets were the most useful improvement in
this project.  Implementing properties didn't make me want to rip my hair out.
Just type 'prop' and hit tab and fill in the blanks.  The built-in snippets for
things like exceptions, attributes, indexers, etc. all work really well.  The
one for implementing an indexer/iterator as a nested class was very interesting as
well. It was also easy to create my own snippets.  I also found the strongly-typed
resources to be very handy.
</p>
        <p>
The debugging stuff is awesome.  I love being able to mouse over variables and
drill into them dynamically.  The little popup windows for exceptions are cool,
but don't really give you any good information that you couldn't get before.
</p>
        <p>
I found the refactoring support to be extremely useful, although it was a little hard
to shift into the mode of making sure everything compiled all the time.  Before,
I would jump around alot in the code, so I would leave things in a state where it
didn't compile.  It worked great once I got used to it.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=3a89ecce-89a8-470e-a894-bc5cc86ce41d" />
      </body>
      <title>STDF Parser/Processor Update</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,3a89ecce-89a8-470e-a894-bc5cc86ce41d.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,3a89ecce-89a8-470e-a894-bc5cc86ce41d.aspx</link>
      <pubDate>Fri, 08 Apr 2005 18:22:28 GMT</pubDate>
      <description>&lt;p&gt;
Last night, I completed my &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=3a89ecce-89a8-470e-a894-bc5cc86ce41d&amp;amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2ce3601f31-231b-4a82-b5a7-1c31600ce25c.aspx"&gt;STDF
file parser that I started over the weekend&lt;/a&gt;.&amp;nbsp; I'm pretty happy with it.&amp;nbsp;
I now fully support all of the version 4 spec.&amp;nbsp; It's written with the Feb. 2005
CTP of Whidbey.&amp;nbsp; It was primarily a good example of a "real world" application,
so I wanted to use it to try out some of the spiffy new features and see how they
might fit into an application that was not built for the sole purpose of showing them
off.
&lt;/p&gt;
&lt;p&gt;
I'm not entirely sure what I should do with it now that I've built it.&amp;nbsp; There's
not much&amp;nbsp;non-commercial&amp;nbsp;demand for something like that that I am aware of.&amp;nbsp;I
might be persuaded to license it for use commercially once there is a "go live" license
for Whidbey.&amp;nbsp; I'm sure it will need some testing to work out issues.&amp;nbsp; I'll
probably build a viewer using it and use it at work to get the kinks out of it.&amp;nbsp;
Anyway, I thought it might be useful to capture how some of these features played
out in a real scenario.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Lightweight Code Generation&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
I used attributes to annotate my record classes in order to define the "on disk" layout
of the record.&amp;nbsp; I originally put the attributes on the properties of the record,
but decided to move them to the class level so that I could define the fields that
are only used for parsing, and not useful after that.&amp;nbsp; At runtime, I register
the record types with the parser, which uses lightweight code generation to generate
converters from unknown records to the concrete records.&amp;nbsp; If you're not familiar
with LCG, it is essentially Reflection.Emit without the overhead of a dynamic assembly,
module, or type.&amp;nbsp; If you're unfamiliar with Reflection.Emit, it is essentially
generating executable IL code on the fly, which has may benefits over generating C#
or some other language and running it through the compiler with CodeDOM or soemthing
else. (If you're not familiar with IL, then this entry is somewhat irrelevant) Having
dealt with assembly on lots of different instruction sets from 68000 to x86 to DSPs
and microcontrollers, I must say that working in IL is wonderful.&amp;nbsp; I was a bit
worried about the startup time for the parser, but it seems to happen very quickly.&amp;nbsp;
I'll need to experiment more to come up with the overhead of the dynamic code.&amp;nbsp;
Again, I was disappointed in the lack of debugging support in LCG.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Generics&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Unfortunately, generics did not work into the equation near as much as I had hoped.&amp;nbsp;
I did find them very useful in places where I would normally pass a Type.&amp;nbsp; Now
I can have a much stronger contract on such methods using generic methods with constraints.&amp;nbsp;
I must say that I love the generic collections.&amp;nbsp; Working with strongly-typed
data without having to generate the classes is very nice.&amp;nbsp; I also like being
able to do a custom sort with an inline&amp;nbsp;anonymous delegate with closure-type
semantics rather than have the overhead of a separate class with the code in a different
place.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Iterators&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Iterators came into play in several places.&amp;nbsp; In the pull-based record parser,
it was simple to implement IEnumerable.&amp;nbsp; I believe it only took 3 or 4 lines
of code.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Delegate type inference&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
I don't remember what the official name of this feature is, but instead of having
to do something like SomeEvent += new EventHandler(SomeMethod), you can just do SomeEvent
+= SomeMethod.&amp;nbsp; This seems small, but I appreciated it quite a bit.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Visual Studio Enhancements&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
These were a very pleasant surprise.&amp;nbsp; I hadn't thought about the exercise as
testing the VS enhancements.&amp;nbsp; The snippets were the most useful improvement in
this project.&amp;nbsp; Implementing properties didn't make me want to rip my hair out.
Just type 'prop' and hit tab and fill in the blanks.&amp;nbsp; The built-in snippets for
things like exceptions, attributes, indexers, etc. all work really well.&amp;nbsp; The
one for implementing an indexer/iterator as a nested class was very interesting as
well. It was also easy to create my own snippets.&amp;nbsp; I also found the strongly-typed
resources to be very handy.
&lt;/p&gt;
&lt;p&gt;
The debugging stuff is awesome.&amp;nbsp; I love being able to mouse over variables and
drill into them dynamically.&amp;nbsp; The little popup windows for exceptions are cool,
but don't really give you any good information that you couldn't get before.
&lt;/p&gt;
&lt;p&gt;
I found the refactoring support to be extremely useful, although it was a little hard
to shift into the mode of making sure everything compiled all the time.&amp;nbsp; Before,
I would jump around alot in the code, so I would leave things in a state where it
didn't compile.&amp;nbsp; It worked great once I got used to it.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=3a89ecce-89a8-470e-a894-bc5cc86ce41d" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,3a89ecce-89a8-470e-a894-bc5cc86ce41d.aspx</comments>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=e3601f31-231b-4a82-b5a7-1c31600ce25c</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,e3601f31-231b-4a82-b5a7-1c31600ce25c.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,e3601f31-231b-4a82-b5a7-1c31600ce25c.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=e3601f31-231b-4a82-b5a7-1c31600ce25c</wfw:commentRss>
      <slash:comments>7</slash:comments>
      <title>Weekend Projects</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,e3601f31-231b-4a82-b5a7-1c31600ce25c.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,e3601f31-231b-4a82-b5a7-1c31600ce25c.aspx</link>
      <pubDate>Mon, 04 Apr 2005 14:57:16 GMT</pubDate>
      <description>&lt;p&gt;
I had two projects over the weekend.&amp;nbsp; One was to get my bathroom ready to install
a new bathtub.&amp;nbsp; The other was an experimental coding project.
&lt;/p&gt;
&lt;p&gt;
The bathroom preparation went fairly well.&amp;nbsp; I ripped out all the cabinets and
countertops.&amp;nbsp; I'm glad my brother showed up unexpectedly because that countertop
was incredibly heavy.&amp;nbsp; We also got alot of the carpet ripped up.&amp;nbsp; I'm going
to be putting down new flooring as well.
&lt;/p&gt;
&lt;p&gt;
On the coding front, as an experiment in adopting new features in Whidbey, I implemented
a binary file parser for Standard Test Datalog Format (STDF)&amp;nbsp;files.&amp;nbsp; These
files make up 99% of the data we work with at work and that fill our many-terabyte
test result database.&amp;nbsp; We have a fairly complex parser and db loader framework,
implemented in C# on 1.x.&amp;nbsp; It works very well, but it was written early on in
our adoption of .net with little knowledge of what the CLR could do for us.&amp;nbsp;So,
my experiment was basically to see how new features in Whidbey, along with my now
deep experience in .net, could make the parser better.
&lt;/p&gt;
&lt;p&gt;
STDF is record-based.&amp;nbsp; The spec defines alot of records, and leaves room for
user-defined records.&amp;nbsp; The new parser reads chunks of the file based on the record
headers&amp;nbsp;and produces "unknown records".&amp;nbsp; I define the record layouts using
attributes on record classes.&amp;nbsp; Then, the parser uses LCG (lightweight code generation
using DynamicMethod) to generate converters to read the content of the unknown records
into the concrete record classes (based on the attributes).&amp;nbsp; The benefit of using
LCG is that record types could be registered or removed on the fly and the GC could
collect the generated code.&amp;nbsp; I could have just as easily implemented it using
on-the-fly interpretation of the attributes.&amp;nbsp; I'll measure and see how the performance
works out.&amp;nbsp; The parser is pull-based, meaning that you ask it for records, or
alternately just "foreach" through them using an iterator-based IEnumerable implementation,
which is pretty sweet.&amp;nbsp; On top of the pull-based parser, I built an event-based
"processor" where a consumer can register to receive certain record types.&amp;nbsp; This
is the model used in our current parser, but after the XmlReader vs. SAX discussions,
I thought exposing the pull-based approach was the right thing to do.
&lt;/p&gt;
&lt;p&gt;
I had a few challenges, which I think represent work for the next version of the CLR:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Endian-ness - To my knowledge the framework does not have any mechanism to work with
binary data with non-native endian-ness.&amp;nbsp; The STDF is written in whatever endian-ness
is native to the platform, so the parser must adapt.&amp;nbsp; This was a simple enough
problem to solve, but now that most of the other gaps have been filled, endian-ness
represents a hole in what the framework provides. 
&lt;li&gt;
Generics' proliferation - Generics are great, and saved me tons of code, but they
have not made their way into the rest of the platform where they could be leveraged.&amp;nbsp;
For instance, if I create a RecordField&lt;T&gt;
, there's not a simple way to do something like BinaryReader.Read&lt;T&gt;
() to actually get one, so I was forced into tons of ifs and switches,&amp;nbsp;and passing
Types around&amp;nbsp;to get the work done.&amp;nbsp; It just didn't feel right. 
&lt;li&gt;
LCG debugging - From what I understand, this was cut from Whidbey.&amp;nbsp; The workaround
for me was to have two generation paths.&amp;nbsp; One would do LCG, and the other would
do traditional Reflection.Emit that could be debugged and PEVerified, etc.&amp;nbsp; The
problem with this was the argument were not aligned between the two.&amp;nbsp; When doing
the traditional Reflection.Emit, ldarg.0 would give you the "this" instance, which
didn't exist in LCG. 
&lt;li&gt;&lt;UNKNOWNRECORD, Mir&gt;&lt;UNKNOWNRECORD, StdfRecord&gt;
Handler registration (Generics compatibility)&amp;nbsp;- Ideally, record handlers should
work with concrete record types, but the way generics work a Converter is not assignable
to a Converter even though Mir : StdfRecord.&amp;nbsp; Of course implementing that would
complicate many things.&amp;nbsp; Interestingly, delegate(UnknownRecord unknownRecord)
{ return new Mir(); } will satisfy both delegate types.&amp;nbsp; So, this was just frustrating
that Generics didn't help me out in solving my record handler registration problems.&amp;nbsp;
There may be a solution that I'm not seeing here because of my approach.&amp;nbsp; Any
ideas?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Oddly enough, I spent about equal time on both projects, but I seem to have alot more
to say about the later.
&lt;/p&gt;
&lt;p&gt;
[UPDATE] I realized that the entry box swallowed some of my generics syntax, so I
fixed that, as well as fixing some minor spelling and grammatical errors.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=e3601f31-231b-4a82-b5a7-1c31600ce25c" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,e3601f31-231b-4a82-b5a7-1c31600ce25c.aspx</comments>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,f155d9f2-11ff-46f3-840f-7bc0f3a0ee15.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,f155d9f2-11ff-46f3-840f-7bc0f3a0ee15.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
For the last 2 months, I've been <a href="http://www.marklio.com/marklio/ct.ashx?id=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15&amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2ccb783789-ec2d-4e5c-917e-3503e02f526e.aspx">having
a blast playing Halo 2</a> with my buddies online. (except <a href="http://www.marklio.com/marklio/ct.ashx?id=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15&amp;url=http%3a%2f%2fjeffandbethanyflint.blogspot.com%2f">Jeff</a>,
who for some reason refuses to get on despite having all the necessary ingredients)
It has worked reasonably well, with the exception of some weird incompatibilities
with certain people.  If they were the party leaders, I'd get the famous "We
are experiencing network issues." message.  Bungie says that this is almost always
caused by NAT incompatibilities.  This didn't get in the way too much because
we could usually juggle around the party leader until everyone could join.
</p>
        <p>
At first, I attributed this to my out-of-the-norm network configuration.  I have
VoIP, so I have several routers.  When I first started playing, I had the <a href="http://www.marklio.com/marklio/ct.ashx?id=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15&amp;url=http%3a%2f%2fwww.d-link.com%2fproducts%2f%3fpid%3d169">VoIP
box</a> as the outer-most router, followed by the venerable <a href="http://www.marklio.com/marklio/ct.ashx?id=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15&amp;url=http%3a%2f%2fwww.linksys.com%2fproducts%2fproduct.asp%3fgrid%3d33%26scid%3d35%26prid%3d601">WRT54G</a>. 
So I was doing a double NAT.  The last several weeks, I've been trying to
reduce my incompatibilities.  First, I managed to set up the VoIP router inside
the firewall (I have <a href="http://www.marklio.com/marklio/ct.ashx?id=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15&amp;url=http%3a%2f%2fwww.usa.att.com%2fcallvantage%2findex.jsp%3fsoac%3d64528">AT&amp;T
CallVantage</a>).  This involved....absolutely nothing.  It simply worked. 
I did set up QoS on the Linksys to ensure the phone would always have enough bandwidth. 
This fixed some of my incompatibilities, but other issues began to crop up, like being
unable to hear everyone in the game lobby sometimes.
</p>
        <p>
I had been running the <a href="http://www.marklio.com/marklio/ct.ashx?id=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15&amp;url=http%3a%2f%2fsourceforge.net%2fprojects%2fwifi-box%2f">wifibox
firmware</a> on the Linksys, and decided to upgrade it to a more recent, official
firmware. So I upgraded to the <a href="http://www.marklio.com/marklio/ct.ashx?id=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15&amp;url=http%3a%2f%2fwww.xbox.com%2fen-US%2flive%2fconnect%2frouterlanding.htm">Live-certified
firmware version</a>.  This didn't help.  Then, after changing nothing,
I began having problems joining people that I had never had trouble with before. 
Last night, after putting the XBox in the DMZ and still having problems, I got
fed up and systematically hunted down the issue.  It was definitely something
with the router, which didn't make sense since it was XBox Live certified, and I was
having trouble with other people who had the same router and they didn't have
problems.  It just didn't add up.
</p>
        <p>
So, I broke down and got a new router, and it fixed everything.  I played until
2:00 this morning without a single problem.  VoIP still works. Wireless works. 
All the PCs work.  All without any additional port forwarding, DMZ settings,
or other configuration besides the QoS.  It just works now.  And do you
want to know the most bizarre part?  I got the exact same model of router.
</p>
        <p>
My conclusion is that the wifi-box firmware screwed it up somehow.  It's the
only variable left in the equation.  I'm curious if anyone else who is running
3rd party firmware has had problems like that. Perhaps I'll link to <a href="http://www.marklio.com/marklio/ct.ashx?id=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15&amp;url=http%3a%2f%2fwww.hanselman.com%2fblog%2fOwnALinkSysWRT54GSveasoftReleasedAlchemyV60RC6AndIHADToInstallItAt2am.aspx">someone
that I know does</a>, and see if that generates any discussion from his previous
post.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15" />
      </body>
      <title>Bizarre XBox Live Router Issues</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,f155d9f2-11ff-46f3-840f-7bc0f3a0ee15.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,f155d9f2-11ff-46f3-840f-7bc0f3a0ee15.aspx</link>
      <pubDate>Sat, 05 Mar 2005 15:59:19 GMT</pubDate>
      <description>&lt;p&gt;
For the last&amp;nbsp;2 months, I've been &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15&amp;amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2ccb783789-ec2d-4e5c-917e-3503e02f526e.aspx"&gt;having
a blast playing Halo 2&lt;/a&gt; with my buddies online. (except &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15&amp;amp;url=http%3a%2f%2fjeffandbethanyflint.blogspot.com%2f"&gt;Jeff&lt;/a&gt;,
who for some reason refuses to get on despite having all the necessary ingredients)
It has worked reasonably well, with the exception of some weird incompatibilities
with certain people.&amp;nbsp; If they were the party leaders, I'd get the famous "We
are experiencing network issues." message.&amp;nbsp; Bungie says that this is almost always
caused by NAT incompatibilities.&amp;nbsp; This didn't get in the way too much because
we could usually juggle around the party leader until everyone could join.
&lt;/p&gt;
&lt;p&gt;
At first, I attributed this to my out-of-the-norm network configuration.&amp;nbsp; I have
VoIP, so I have several routers.&amp;nbsp; When I first started playing, I had the &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15&amp;amp;url=http%3a%2f%2fwww.d-link.com%2fproducts%2f%3fpid%3d169"&gt;VoIP
box&lt;/a&gt;&amp;nbsp;as the outer-most router, followed by the venerable &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15&amp;amp;url=http%3a%2f%2fwww.linksys.com%2fproducts%2fproduct.asp%3fgrid%3d33%26scid%3d35%26prid%3d601"&gt;WRT54G&lt;/a&gt;.&amp;nbsp;
So I was&amp;nbsp;doing a double NAT.&amp;nbsp; The last several weeks, I've been trying to
reduce my incompatibilities.&amp;nbsp; First, I managed to set up the VoIP router inside
the firewall (I have &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15&amp;amp;url=http%3a%2f%2fwww.usa.att.com%2fcallvantage%2findex.jsp%3fsoac%3d64528"&gt;AT&amp;amp;T
CallVantage&lt;/a&gt;).&amp;nbsp; This involved....absolutely nothing.&amp;nbsp; It simply worked.&amp;nbsp;
I did set up QoS on the Linksys to ensure the phone would always have enough bandwidth.&amp;nbsp;
This fixed some of my incompatibilities, but other issues began to crop up, like being
unable to hear everyone in the game lobby sometimes.
&lt;/p&gt;
&lt;p&gt;
I had been running the &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15&amp;amp;url=http%3a%2f%2fsourceforge.net%2fprojects%2fwifi-box%2f"&gt;wifibox
firmware&lt;/a&gt; on the Linksys, and decided to upgrade it to a more recent, official
firmware. So I upgraded to the &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15&amp;amp;url=http%3a%2f%2fwww.xbox.com%2fen-US%2flive%2fconnect%2frouterlanding.htm"&gt;Live-certified
firmware version&lt;/a&gt;.&amp;nbsp; This didn't help.&amp;nbsp; Then, after changing nothing,
I began having problems joining people that I had never had trouble with before.&amp;nbsp;
Last night, after putting the XBox in the DMZ and still having problems,&amp;nbsp;I got
fed up and systematically hunted down the issue.&amp;nbsp; It was definitely something
with the router, which didn't make sense since it was XBox Live certified, and I was
having trouble with&amp;nbsp;other people who had the same router and they didn't have
problems.&amp;nbsp; It just didn't add up.
&lt;/p&gt;
&lt;p&gt;
So, I broke down and got a new router, and it fixed everything.&amp;nbsp; I played until
2:00 this morning without a single problem.&amp;nbsp; VoIP still works. Wireless works.&amp;nbsp;
All the PCs work.&amp;nbsp; All without any additional port forwarding, DMZ settings,
or other configuration besides the QoS.&amp;nbsp; It just works now.&amp;nbsp; And do you
want to know the most bizarre part?&amp;nbsp; I got the exact same model of router.
&lt;/p&gt;
&lt;p&gt;
My conclusion is that the wifi-box firmware screwed it up somehow.&amp;nbsp; It's the
only variable left in the equation.&amp;nbsp; I'm curious if anyone else who is running
3rd party firmware has had problems like that. Perhaps I'll link to &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15&amp;amp;url=http%3a%2f%2fwww.hanselman.com%2fblog%2fOwnALinkSysWRT54GSveasoftReleasedAlchemyV60RC6AndIHADToInstallItAt2am.aspx"&gt;someone
that I know does&lt;/a&gt;,&amp;nbsp;and see if that generates any discussion from his previous
post.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=f155d9f2-11ff-46f3-840f-7bc0f3a0ee15" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,f155d9f2-11ff-46f3-840f-7bc0f3a0ee15.aspx</comments>
      <category>Crazy stuff</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=de2d61ba-30bc-458f-bcf5-b1f5f697647d</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,de2d61ba-30bc-458f-bcf5-b1f5f697647d.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,de2d61ba-30bc-458f-bcf5-b1f5f697647d.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=de2d61ba-30bc-458f-bcf5-b1f5f697647d</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I've been toying with ECMAScript for the past week or so, mostly to update some dynamic
user interface elements in a web application we have.  Every time I use it, I'm
always impressed at the cool things I can do with it.  It also makes me wish
that Microsoft had not messed with it as part of the CLR (JScript.NET).  Their
newest version of JScript seems to merely make it into an alternate syntax, and not
really take advantage of what it could do as a prototype-driven language with closure
support.
</p>
        <p>
I found this <a href="http://www.marklio.com/marklio/ct.ashx?id=de2d61ba-30bc-458f-bcf5-b1f5f697647d&amp;url=http%3a%2f%2fwww.crockford.com%2fjavascript%2fjavascript.html">article
that claims that it is the world's most misunderstood language</a>.  I think
I agree.  It's incredibly powerful, but very underutilized because of the confusion
surrounding it.  Closures coupled with prototypes can yield some very slick code
if you understand what you're doing (and I guess maybe that's the problem). 
All you really need is a nice IDE to help you manage your objects and their prototype
chain.
</p>
        <p>
I'm also getting more into Python and Ruby, which are also very slick.  I'm just
not sure how they should fit into a project.  In general, a project with fewer
languages is more maintainable.  But imagine trying to build a skyscraper when
your only tool is a hammer that works really well. (OK, maybe hammer is not the best
analogy.  Maybe a blowtorch?  I don't know)
</p>
        <p>
[UPDATE] I just had to include <a href="http://www.marklio.com/marklio/ct.ashx?id=de2d61ba-30bc-458f-bcf5-b1f5f697647d&amp;url=http%3a%2f%2fwww.crockford.com%2fjavascript%2finheritance.html">this
link</a>, where the author shows us how to do lot of different code reuse patterns,
including multiple inheritance in Javascript.  My favorite quote:
</p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <em>This large set of code reuse patterns comes from a language which is considered
smaller and simpler than Java</em>
          </p>
        </blockquote>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=de2d61ba-30bc-458f-bcf5-b1f5f697647d" />
      </body>
      <title>ECMAScript/Javascript/JScript and other under-utilized languages</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,de2d61ba-30bc-458f-bcf5-b1f5f697647d.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,de2d61ba-30bc-458f-bcf5-b1f5f697647d.aspx</link>
      <pubDate>Mon, 28 Feb 2005 18:56:23 GMT</pubDate>
      <description>&lt;p&gt;
I've been toying with ECMAScript for the past week or so, mostly to update some dynamic
user interface elements in a web application we have.&amp;nbsp; Every time I use it, I'm
always impressed at the cool things I can do with it.&amp;nbsp; It also makes me wish
that Microsoft had not messed with it as part of the CLR (JScript.NET).&amp;nbsp; Their
newest version of JScript seems to merely make it into an alternate syntax, and not
really take advantage of what it could do as a prototype-driven language with closure
support.
&lt;/p&gt;
&lt;p&gt;
I found this &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=de2d61ba-30bc-458f-bcf5-b1f5f697647d&amp;amp;url=http%3a%2f%2fwww.crockford.com%2fjavascript%2fjavascript.html"&gt;article
that claims that it is the world's most misunderstood language&lt;/a&gt;.&amp;nbsp; I think
I agree.&amp;nbsp; It's incredibly powerful, but very underutilized because of the confusion
surrounding it.&amp;nbsp; Closures coupled with prototypes can yield some very slick code
if you understand what you're doing (and I guess maybe that's the problem).&amp;nbsp;
All you really need is a nice IDE to help you manage your objects and their prototype
chain.
&lt;/p&gt;
&lt;p&gt;
I'm also getting more into Python and Ruby, which are also very slick.&amp;nbsp; I'm just
not sure how they should fit into a project.&amp;nbsp; In general, a project with fewer
languages is more maintainable.&amp;nbsp; But imagine trying to build a skyscraper when
your only tool is a hammer that works really well. (OK, maybe hammer is not the best
analogy.&amp;nbsp; Maybe a blowtorch?&amp;nbsp; I don't know)
&lt;/p&gt;
&lt;p&gt;
[UPDATE] I just had to include &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=de2d61ba-30bc-458f-bcf5-b1f5f697647d&amp;amp;url=http%3a%2f%2fwww.crockford.com%2fjavascript%2finheritance.html"&gt;this
link&lt;/a&gt;, where the author shows us how to do lot of different code reuse patterns,
including multiple inheritance in Javascript.&amp;nbsp; My favorite quote:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
&lt;em&gt;This large set of code reuse patterns comes from a language which is considered
smaller and simpler than Java&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt;&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=de2d61ba-30bc-458f-bcf5-b1f5f697647d" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,de2d61ba-30bc-458f-bcf5-b1f5f697647d.aspx</comments>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=8a72999b-dbbc-4797-96a8-3d005b346ed8</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,8a72999b-dbbc-4797-96a8-3d005b346ed8.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,8a72999b-dbbc-4797-96a8-3d005b346ed8.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=8a72999b-dbbc-4797-96a8-3d005b346ed8</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">Turns out, <a href="http://www.marklio.com/marklio/ct.ashx?id=8a72999b-dbbc-4797-96a8-3d005b346ed8&amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2c0575ae50-07e8-4274-b7fb-2b7900a18128.aspx">my
problem with metadata in my pictures</a> was I didn't have the <a href="http://www.marklio.com/marklio/ct.ashx?id=8a72999b-dbbc-4797-96a8-3d005b346ed8&amp;url=http%3a%2f%2fwww.adobe.com%2fsupport%2fdownloads%2fproduct.jsp%3fproduct%3d39%26platform%3dWindows">latest
RAW support</a> installed.  This was evidently something that Adobe fixed. 
Oh well, at least I learned alot about XMP and got more of the Flickr API implemented. 
I'll have to come up with a strategy for replacing 1GB of pictures.  I also want
to add a few more steps in my processing.  Alot of the pictures turned out a
little dull.  I think I won't be in such a hurry to get them uploaded in the
future.<img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=8a72999b-dbbc-4797-96a8-3d005b346ed8" /></body>
      <title>Flickr Metadata update</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,8a72999b-dbbc-4797-96a8-3d005b346ed8.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,8a72999b-dbbc-4797-96a8-3d005b346ed8.aspx</link>
      <pubDate>Tue, 15 Feb 2005 16:15:06 GMT</pubDate>
      <description>Turns out, &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=8a72999b-dbbc-4797-96a8-3d005b346ed8&amp;amp;url=http%3a%2f%2fwww.marklio.com%2fmarklio%2fPermaLink%2cguid%2c0575ae50-07e8-4274-b7fb-2b7900a18128.aspx"&gt;my
problem with metadata in my pictures&lt;/a&gt; was I didn't have the &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=8a72999b-dbbc-4797-96a8-3d005b346ed8&amp;amp;url=http%3a%2f%2fwww.adobe.com%2fsupport%2fdownloads%2fproduct.jsp%3fproduct%3d39%26platform%3dWindows"&gt;latest
RAW support&lt;/a&gt; installed.&amp;nbsp; This was evidently something that Adobe fixed.&amp;nbsp;
Oh well, at least I learned alot about XMP and got more of the Flickr API implemented.&amp;nbsp;
I'll have to come up with a strategy for replacing 1GB of pictures.&amp;nbsp; I also want
to add a few more steps in my processing.&amp;nbsp; Alot of the pictures turned out a
little dull.&amp;nbsp; I think I won't be in such a hurry to get them uploaded in the
future.&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=8a72999b-dbbc-4797-96a8-3d005b346ed8" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,8a72999b-dbbc-4797-96a8-3d005b346ed8.aspx</comments>
      <category>Fun</category>
      <category>Photography</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=0575ae50-07e8-4274-b7fb-2b7900a18128</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,0575ae50-07e8-4274-b7fb-2b7900a18128.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,0575ae50-07e8-4274-b7fb-2b7900a18128.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=0575ae50-07e8-4274-b7fb-2b7900a18128</wfw:commentRss>
      <slash:comments>5</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Whew, what an ordeal.  I finally got my Adobe Photoshop CS in the other day,
and last night, I created a "Droplet" for batch converting all my raw files from my
Canon Digital Rebel. Droplets are a really sweet feature that lets you create a little
executable from recorded actions for batch operations.  So, I burned through
about 2000 images, creating big jpgs suitable for uploading to my newly upgraded <a href="http://www.marklio.com/marklio/ct.ashx?id=0575ae50-07e8-4274-b7fb-2b7900a18128&amp;url=http%3a%2f%2fwww.flickr.com%2fphotos%2fmarklio%2f">Flickr
account</a>.  It was getting pretty late, so I fired up an uploader an set it
to upload my 1GB limit (roughly 900 pictures).
</p>
        <p>
This morning, I checked my account, only to find that none of the metadata had been
uploaded.  All my images appeared to have been taken on Feb 11, 2005...uh oh. 
So, I set out to find out what happened.  Turns out, Photoshop saves the
metadata in it's <a href="http://www.marklio.com/marklio/ct.ashx?id=0575ae50-07e8-4274-b7fb-2b7900a18128&amp;url=http%3a%2f%2fwww.adobe.com%2fproducts%2fxmp%2f">XMP
format</a> within the file. XMP is simply an rdf encoding of the data in an XML payload
within the file.  It's actually pretty cool, but Flickr doesn't read this data
yet.  So I set out to "fix" my pictures, since I can't upload anymore until next
month and I have lots more to upload.
</p>
        <p>
After looking at lots of libraries and <a href="http://www.marklio.com/marklio/ct.ashx?id=0575ae50-07e8-4274-b7fb-2b7900a18128&amp;url=http%3a%2f%2fpartners.adobe.com%2fpublic%2fdeveloper%2fxmp%2fsdk%2findex.html">Adobe's
XMP SDK</a>, I decided it would be easy enough to pull the data out myself. 
So, I built a little app using my FlickrApi library I just created that would blast
through my uploaded pictures, find the corresponding image on my local pc, pull the
xmp data out of the file, and set the "date taken" on the Flickr site.  That
way, I can at least organize them more easily.
</p>
        <p>
It worked perfectly.  It blasted through about 900MB in less than a minute. 
Look for the pictures as I tag them, annotate them, and change them from private to
public.  I'll have to see if there's a way to have Photoshop preserve that data
next time because I'd really like to have the rest of the metadata available. 
I'll probably make my XMP parser available as well if anyone's interested.  As
far as I know, there is not another managed implementation available.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=0575ae50-07e8-4274-b7fb-2b7900a18128" />
      </body>
      <title>Loading Flickr</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,0575ae50-07e8-4274-b7fb-2b7900a18128.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,0575ae50-07e8-4274-b7fb-2b7900a18128.aspx</link>
      <pubDate>Sat, 12 Feb 2005 22:59:33 GMT</pubDate>
      <description>&lt;p&gt;
Whew, what an ordeal.&amp;nbsp; I finally got my Adobe Photoshop CS in the other day,
and last night, I created a "Droplet" for batch converting all my raw files from my
Canon Digital Rebel. Droplets are a really sweet feature that lets you create a little
executable from recorded actions for&amp;nbsp;batch operations.&amp;nbsp; So, I burned through
about 2000 images, creating big jpgs suitable for uploading to my newly upgraded &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=0575ae50-07e8-4274-b7fb-2b7900a18128&amp;amp;url=http%3a%2f%2fwww.flickr.com%2fphotos%2fmarklio%2f"&gt;Flickr
account&lt;/a&gt;.&amp;nbsp; It was getting pretty late, so I fired up an uploader an set it
to upload my 1GB limit (roughly 900 pictures).
&lt;/p&gt;
&lt;p&gt;
This morning, I checked my account, only to find that none of the metadata had been
uploaded.&amp;nbsp; All my images appeared to have been taken on Feb 11, 2005...uh oh.&amp;nbsp;
So, I set out&amp;nbsp;to find out what happened.&amp;nbsp; Turns out, Photoshop saves the
metadata in it's &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=0575ae50-07e8-4274-b7fb-2b7900a18128&amp;amp;url=http%3a%2f%2fwww.adobe.com%2fproducts%2fxmp%2f"&gt;XMP
format&lt;/a&gt; within the file. XMP is simply an rdf encoding of the data in an XML payload
within the file.&amp;nbsp; It's actually pretty cool, but Flickr doesn't read this data
yet.&amp;nbsp; So I set out to "fix" my pictures, since I can't upload anymore until next
month and I have lots more to upload.
&lt;/p&gt;
&lt;p&gt;
After looking at lots of libraries and &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=0575ae50-07e8-4274-b7fb-2b7900a18128&amp;amp;url=http%3a%2f%2fpartners.adobe.com%2fpublic%2fdeveloper%2fxmp%2fsdk%2findex.html"&gt;Adobe's
XMP SDK&lt;/a&gt;, I decided it would be easy enough to pull the data out myself.&amp;nbsp;
So, I built a little app using my FlickrApi library I just created that would blast
through my uploaded pictures, find the corresponding image on my local pc, pull the
xmp data out of the file, and set the "date taken" on the Flickr site.&amp;nbsp; That
way, I can at least organize them more easily.
&lt;/p&gt;
&lt;p&gt;
It worked perfectly.&amp;nbsp; It blasted through about 900MB in less than a minute.&amp;nbsp;
Look for the pictures as I tag them, annotate them, and change them from private to
public.&amp;nbsp; I'll have to see if there's a way to have Photoshop preserve that data
next time because I'd really like to have the rest of the metadata available.&amp;nbsp;
I'll probably make my XMP parser available as well if anyone's interested.&amp;nbsp; As
far as I know, there is not another managed implementation available.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=0575ae50-07e8-4274-b7fb-2b7900a18128" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,0575ae50-07e8-4274-b7fb-2b7900a18128.aspx</comments>
      <category>Crazy stuff</category>
      <category>Fun</category>
      <category>Photography</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=9db1eadc-1472-4134-b8e1-02a89a7bb34a</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,9db1eadc-1472-4134-b8e1-02a89a7bb34a.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,9db1eadc-1472-4134-b8e1-02a89a7bb34a.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=9db1eadc-1472-4134-b8e1-02a89a7bb34a</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Last night, I made alot of progress creating a .NET API for Flickr.  There doesn't
seem to be alot of activity on the <a href="http://www.marklio.com/marklio/ct.ashx?id=9db1eadc-1472-4134-b8e1-02a89a7bb34a&amp;url=http%3a%2f%2fflickrdotnet.wdevs.com%2f">Flickr.NET</a> project,
and I don't like some of the decisions they made in the design.  They seem to
have taken a direct wrapping approach to it rather than designing an API that fits
in the .NET world.  It's amazing how spoiled you get when you're used to using
good API's.  You start saying things like, "You mean I get an array back from
this method?  Eww."  or "That's a silly name for that member."  Of
course, it's probably appropriate to note that Flickr.NET seems to have been created
with an emphasis on uploading.  I'm more interested in sifting through the metadata.
</p>
        <p>
Anyway, I've got most of the functionality that I'm interested in implemented, and
I'll be doing the rest a little at a time.  I've used the <a href="http://www.marklio.com/marklio/ct.ashx?id=9db1eadc-1472-4134-b8e1-02a89a7bb34a&amp;url=http%3a%2f%2fmsdn.microsoft.com%2flibrary%2fdefault.asp%3furl%3d%2flibrary%2fen-us%2fcpgenref%2fhtml%2fcpconnetframeworkdesignguidelines.asp">design
guidelines</a> fairly strictly, and I think I'm coming up with something that's
really approachable for .NET users, and is still correlated enough to the <a href="http://www.marklio.com/marklio/ct.ashx?id=9db1eadc-1472-4134-b8e1-02a89a7bb34a&amp;url=http%3a%2f%2fwww.flickr.com%2fservices%2fapi%2f">Flickr
API documentation</a> that the parallels are easily discoverable.  You may notice
some bizarreness here as I play with the different kinds of integration I have
planned for my blog.
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=9db1eadc-1472-4134-b8e1-02a89a7bb34a" />
      </body>
      <title>Flickr API Progress</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,9db1eadc-1472-4134-b8e1-02a89a7bb34a.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,9db1eadc-1472-4134-b8e1-02a89a7bb34a.aspx</link>
      <pubDate>Fri, 11 Feb 2005 15:36:12 GMT</pubDate>
      <description>&lt;p&gt;
Last night, I made alot of progress creating a .NET API for Flickr.&amp;nbsp; There doesn't
seem to be alot of activity on the&amp;nbsp;&lt;a href="http://www.marklio.com/marklio/ct.ashx?id=9db1eadc-1472-4134-b8e1-02a89a7bb34a&amp;amp;url=http%3a%2f%2fflickrdotnet.wdevs.com%2f"&gt;Flickr.NET&lt;/a&gt; project,
and I don't like some of the decisions they made in the design.&amp;nbsp; They seem to
have taken a direct wrapping approach to it rather than designing an API that fits
in the .NET world.&amp;nbsp; It's amazing how spoiled you get when you're used to using
good API's.&amp;nbsp; You start saying things like, "You mean I get an array back from
this method?&amp;nbsp; Eww."&amp;nbsp; or "That's a silly name for that member."&amp;nbsp; Of
course, it's probably appropriate to note that Flickr.NET seems to have been created
with an emphasis on uploading.&amp;nbsp; I'm more interested in sifting through the&amp;nbsp;metadata.
&lt;/p&gt;
&lt;p&gt;
Anyway, I've got most of the functionality that I'm interested in implemented, and
I'll be doing the rest a little at a time.&amp;nbsp; I've used the &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=9db1eadc-1472-4134-b8e1-02a89a7bb34a&amp;amp;url=http%3a%2f%2fmsdn.microsoft.com%2flibrary%2fdefault.asp%3furl%3d%2flibrary%2fen-us%2fcpgenref%2fhtml%2fcpconnetframeworkdesignguidelines.asp"&gt;design
guidelines&lt;/a&gt;&amp;nbsp;fairly strictly, and I think I'm coming up with something that's
really approachable for .NET users, and is still correlated enough to the &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=9db1eadc-1472-4134-b8e1-02a89a7bb34a&amp;amp;url=http%3a%2f%2fwww.flickr.com%2fservices%2fapi%2f"&gt;Flickr
API documentation&lt;/a&gt; that the parallels are easily discoverable.&amp;nbsp; You may notice
some bizarreness here as I play with the&amp;nbsp;different kinds of integration I have
planned for my blog.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=9db1eadc-1472-4134-b8e1-02a89a7bb34a" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,9db1eadc-1472-4134-b8e1-02a89a7bb34a.aspx</comments>
      <category>Photography</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
    <item>
      <trackback:ping>http://www.marklio.com/marklio/Trackback.aspx?guid=4d0e17b0-776e-4a2a-940c-a8f7d1e7b162</trackback:ping>
      <pingback:server>http://www.marklio.com/marklio/pingback.aspx</pingback:server>
      <pingback:target>http://www.marklio.com/marklio/PermaLink,guid,4d0e17b0-776e-4a2a-940c-a8f7d1e7b162.aspx</pingback:target>
      <dc:creator>Mark</dc:creator>
      <wfw:comment>http://www.marklio.com/marklio/CommentView,guid,4d0e17b0-776e-4a2a-940c-a8f7d1e7b162.aspx</wfw:comment>
      <wfw:commentRss>http://www.marklio.com/marklio/SyndicationService.asmx/GetEntryCommentsRss?guid=4d0e17b0-776e-4a2a-940c-a8f7d1e7b162</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://www.marklio.com/marklio/ct.ashx?id=4d0e17b0-776e-4a2a-940c-a8f7d1e7b162&amp;url=http%3a%2f%2fwww.marumushi.com%2fapps%2fflickrgraph%2f">This</a> is
one of the coolest things I've seen in a long time.  Try my flickr name (marklio). 
It lets you drill through my contacts and see their information.  Keeping clicking
and you'll see all kinds of cool things.  It really helped me see <a href="http://www.marklio.com/marklio/ct.ashx?id=4d0e17b0-776e-4a2a-940c-a8f7d1e7b162&amp;url=http%3a%2f%2fwww.flickr.com%2f">Flickr</a> as
a web service rather than just a photo sharing site.  It gave me alot of ideas. 
Things like using tag matching to automatically creating blog entry backgrounds that
are relevant to the content.  I'm going to be playing with that.
</p>
        <p>
Their <a href="http://www.marklio.com/marklio/ct.ashx?id=4d0e17b0-776e-4a2a-940c-a8f7d1e7b162&amp;url=http%3a%2f%2fwww.flickr.com%2fservices%2fapi%2f">API</a> is
really nice and well-documented.  Some people made a <a href="http://www.marklio.com/marklio/ct.ashx?id=4d0e17b0-776e-4a2a-940c-a8f7d1e7b162&amp;url=http%3a%2f%2fwdevs.com%2fDefault.aspx%3ftabid%3d86">.NET
wrapper for the API</a>, but it's not up-to-date and I wasn't really impressed with
the design.  I'll probably roll my own and just implement the things I need as
I go.
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=4d0e17b0-776e-4a2a-940c-a8f7d1e7b162" />
      </body>
      <title>Awesome Flickr Application</title>
      <guid isPermaLink="false">http://www.marklio.com/marklio/PermaLink,guid,4d0e17b0-776e-4a2a-940c-a8f7d1e7b162.aspx</guid>
      <link>http://www.marklio.com/marklio/PermaLink,guid,4d0e17b0-776e-4a2a-940c-a8f7d1e7b162.aspx</link>
      <pubDate>Thu, 10 Feb 2005 04:52:26 GMT</pubDate>
      <description>&lt;p&gt;
&lt;a href="http://www.marklio.com/marklio/ct.ashx?id=4d0e17b0-776e-4a2a-940c-a8f7d1e7b162&amp;amp;url=http%3a%2f%2fwww.marumushi.com%2fapps%2fflickrgraph%2f"&gt;This&lt;/a&gt; is
one of the coolest things I've seen in a long time.&amp;nbsp; Try my flickr name (marklio).&amp;nbsp;
It lets you drill through my contacts and see their information.&amp;nbsp; Keeping clicking
and you'll see all kinds of cool things.&amp;nbsp; It really helped me see &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=4d0e17b0-776e-4a2a-940c-a8f7d1e7b162&amp;amp;url=http%3a%2f%2fwww.flickr.com%2f"&gt;Flickr&lt;/a&gt; as
a web service rather than just a photo sharing site.&amp;nbsp; It gave me alot of ideas.&amp;nbsp;
Things like using tag matching to automatically creating blog entry backgrounds that
are relevant to the content.&amp;nbsp; I'm going to be playing with that.
&lt;/p&gt;
&lt;p&gt;
Their &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=4d0e17b0-776e-4a2a-940c-a8f7d1e7b162&amp;amp;url=http%3a%2f%2fwww.flickr.com%2fservices%2fapi%2f"&gt;API&lt;/a&gt; is
really nice and well-documented.&amp;nbsp; Some people made a &lt;a href="http://www.marklio.com/marklio/ct.ashx?id=4d0e17b0-776e-4a2a-940c-a8f7d1e7b162&amp;amp;url=http%3a%2f%2fwdevs.com%2fDefault.aspx%3ftabid%3d86"&gt;.NET
wrapper for the API&lt;/a&gt;, but it's not up-to-date and I wasn't really impressed with
the design.&amp;nbsp; I'll probably roll my own and just implement the things I need as
I go.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.marklio.com/marklio/aggbug.ashx?id=4d0e17b0-776e-4a2a-940c-a8f7d1e7b162" /&gt;</description>
      <comments>http://www.marklio.com/marklio/CommentView,guid,4d0e17b0-776e-4a2a-940c-a8f7d1e7b162.aspx</comments>
      <category>Crazy stuff</category>
      <category>Fun</category>
      <category>Software Development</category>
      <category>Technical</category>
    </item>
  </channel>
</rss>