Monday, February 8, 2010

Redirecting Assembly Bindings in .NET 3.5

I spent some time last week digging into assembly binding redirection.  This blog post provides working examples of assembly redirection through config files and publisher policies.

This example will use the following command line utilities and versions:
  • csc - C# compiler (Version 3.5.30729.4926)
  • sn - .Strong Name Utility (Version 3.5.30729.1)
  • gacutil - Global Assembly Cache Tool (Version 3.5.30729.1)
  • al - assembly linker (Version 8.00.50727.42)
Helpful utilities not covered in this article:
To get started lets create a program calling a method in another assembly which outputs the callee's assembly version.  These steps also create assemblies for use in the later examples.
  1. Open a Visual Studio Command Prompt and navigate to a working directory where some files can be created.
  2. Create and save a file named demo.cs containing the following text:
    using System;
    using System.Reflection;

    [assembly: AssemblyVersionAttribute("2.0.0.0")]

    public static class Demo
    {
        public static void Main()
        {
            Console.WriteLine("Version " + Assembly.GetExecutingAssembly().GetName().Version.ToString());
        }
    }
  3. from a command prompt type "sn -k key.snk"
  4. type "csc /target:library /keyfile:key.snk demo.cs"
  5. type "echo f | xcopy demo.dll .\bin\v2\demo.dll"
  6. Change the AssemblyVersionAttribute in demo.cs replacing "2.0" with "3.0"
  7. csc /target:library /keyfile:key.snk demo.cs
  8. echo f | xcopy demo.dll .\bin\v3\demo.dll
  9. Change the AssemblyVersionAttribute in demo.cs replacing "3.0" with "4.0"
  10. csc /target:library /keyfile:key.snk demo.cs
  11. echo f | xcopy demo.dll .\bin\v4\demo.dll
  12. Change the AssemblyVersionAttribute in demo.cs replacing "4.0" with "1.0"
  13. csc /target:libarary /keyfile:key.snk demo.cs
    1. echo f | xcopy demo.dll .\bin\v1\demo.dll
  14. Create and save a file named demo.cs containing the following text:
    public static class Program
    {
        public static void Main()
        {
            Demo.Main();
        }
    }
  15. csc /reference:demo.dll program.cs
  16. program.exe
  17. The output should read: Version 1.0.0.0
Redirecting 1.0 to 2.0 version in the GAC.
  1. gacutil /i .\bin\v2\demo.dll
  2. sn -T demo.dll
  3. Note the Public key token as we'll need that in the assemblyIdentity publicKeyToken attribute in the next step.
  4. Create program.exe.config with the following text:
    <?xml version="1.0"?>
    <
    configuration>
     <
    runtime>
      <
    assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
       <
    dependentAssembly>
        <
    assemblyIdentity name="demo" publicKeyToken="keyFromSn-T" />
        <
    bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" />
       </
    dependentAssembly>
      </
    assemblyBinding>
     </
    runtime>
    </
    configuration>
  5. program.exe
  6. The output should read:  Version 2.0.0.0
Redirecting 1.0 to Version 3.0 using a URL:
  1. Replace the program.exe.config text with the following:
    <?xml version="1.0"?>
    <configuration>
     <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
       <dependentAssembly>
         <assemblyIdentity name="demo" publicKeyToken="keyFromSn-T" />
         <bindingRedirect oldVersion="1.0.0.0newVersion="3.0.0.0"/>
            <!--to use an absolute filepath use href="file://D:/Projects/...." or it can point to a web resource: href="http://www.fake.com/demo.dll"-->
         <codeBase version="3.0.0.0" href="./bin/v3/demo.dll" />
        </dependentAssembly>
      </assemblyBinding>
     </runtime>
    </configuration>
  2. program.exe
  3. The output should read: Version 3.0.0.0
Redirecting 1.0 to Version 4.0 in the GAC using a publisher policy.
  1. Create a policy.config file in the working directory with this text:
    <?xml version="1.0"?>
    <configuration>
     <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
       <dependentAssembly>
        <assemblyIdentity name="demo" publicKeyToken="keyFromSn-T" />
        <bindingRedirect oldVersion="1.0.0.0" newVersion="4.0.0.0" />
       </dependentAssembly>
      </assemblyBinding>
     </runtime>
    </configuration>
  2. al /link:policy.config /out:policy.1.0.demo.dll /keyfile:key.snk
  3. gacutil /i policy.1.0.demo.dll
  4. gacutil /i .\bin\v4\demo.dll
  5. delete the program.exe.config in the working directory or erase the bindingredirect element.  The bindingredirects seem to be applied first and will break this example.
  6. program.exe
  7. The output should read: Version 4.0.0.0

5 comments:

Anonymous said...

[... ] is one must read source of tips on this issue[...]

hire .net programmer said...

This blog post provides working examples of assembly redirection through config files which is good.I like the article as it is informative.

Anonymous said...

After reading you site, Your site is very useful for me .I bookmarked your site!

Anonymous said...

i surely enjoy your own writing kind, very exciting.
don't give up as well as keep penning as it just good worth to read it.
looking forward to see far more of your current stories, regards :)

Anonymous said...

i think you should validate your html, it got errors