views:

113

answers:

2

I have a question about how the .NET framework (2.0) resolves dependent assemblies.

We're currently involved in a bit of a rewrite of a large ASP.NET application and various satellite executables. There are also some nagging problems with our foundation classes that we developed a new API to solve. So far this is a normal, albeit wide-reaching, update.

Our heirarchy is:

  1. ASP.NET (aspx)
  2. business logic (DLLs)
  3. foundation classes (DLLs)

So ASP.NET doesn't throw a fit, some of the DLLs (specifically the foundation classes) have a redirection layer that contains the old namespaces/functions and forwards them to the new API. When we replaced the DLLs, ASP.NET picked them up fine (probably because it triggered a recompile).

Precompiled applications don't though, even though the same namespaces and classes are in both sets of DLLs. Even when the file is renamed, it complains about the assemblyname attribute being different (which it has to be by necessity). I know you can redirect to differnet versions of the same assembly, but is there any way to direct to a completely different assembly?

The alternatives are to recompile the applications (don't really want to because the applications themselves haven't changed) or recompile the old foundation DLL with stubs refering to the new foundation DLL (the new dummy DLL is file system clutter).

+2  A: 

You want to move the types to a new assembly? You can do that with [TypeForwardedTo(..)].

If you originally have (AssemblyA):

namespace SomeNamespace {
    public class SomeType {}
}

You can instead move that type into AssemblyB, and have a virtually empty AssemblyA which references AssemblyB and simply contains:

[assembly: TypeForwardedTo(typeof(SomeNamespace.SomeType))]

Then anything trying to load SomeNamespace.SomeType from AssemblyA actually gets the type from AssemblyB.

Most of the runtime respects this attribute... everything except WCF extensions. Which bit me ;-p Oh, and it isn't a fan of nested types...

Marc Gravell
I was hoping to get away with no having to tough either the original application or the old API libraries. While the TypeForwarder is an interesting concept, it won't work in this case. RK1.DLL has RK1.API.FUNCTION(). RK2.DLL has RK2.API.Function() and RK1.API1.FUNCTION() which forwards back to RK2.API2.Function(). Because of this, RK1.DLL and RK2.DLL can't be called by the same application and I presume the compiler would barf if I tried to forward a type to what it thinkis is itself. I just wanted a way to drop RK2.DLL in, rename RK1.DLL to RK1.notaDLL, and have the application work.
RK
I was just surprised that the framework had support for forcing an application to redirect by version at runtime but no way (that I've found) to forward to another assembly without recompiling somewhere.
RK
@RK - blind shot in the dark; have you tried `AppDomain.CurrentDomain.AssemblyResolve`? If it fails to find the first assembly, you can handle this and return the new assembly (via `Assembly.Load(newName)`...
Marc Gravell
Yes, I did find that option, but it still seems to require recompiling the caller applications. If I'm going to recompile the applications anyway, I might as well point the reference at the right file while I'm at it.
RK
A: 
//File: RKAPPLET.EXE
namespace RKAPPLET
{
  using RKMFC;
  public static class Program
  {
    public static void Main ()
    {
      RKMFC.API.DoSomething();
    }
  }
}

//File: RKMFC.DLL
namespace RKMFC
{
  public static class API
  {
    public static void DoSomething ()
    {
      System.Windows.Forms.MessageBox.Show("MFC!")
    }
  }
}

//File: RKNET.DLL
namespace RKNET
{
  public static class API
  {
    public static void DoSomethingElse ()
    {
      System.Windows.Forms.MessageBox.Show("NET!")
    }
  }
}
namespace RKMFC
{
  public static class API
  {
    public static void DoSomething ()
    {
      RKNET.API.DoSomethingElse()
    }
  }
}

I want RKAPPLET.EXE, compiled with RKMFC.DLL, to find RKNET.DLL (which has a copy of everything in RKMFC.DLL and then some) without recompiling either RKAPPLET.EXE (to point to it) or RKMFC.DLL (to redirect types).

RK