Cross Language References in ASP.NET

ppl-crwd-018

Most ASP.NET programmers are aware that the environment allows programmers to write code in multiple languages.  This is what allows a programmer who prefers CSharp to write modules for DotNetNuke in CSharp even though the core code is written in VB.NET.  (Until version 6.0, anyhow, where the core will finally be written in CSharp.)

What many don’t realize is that you can’t have CSharp code reference VB.NET and also have VB.NET code reference the CSharp code within the same application.  At least, you can’t do it directly.

The project I’m working on is primarily written in VB.NET.  It’s the 5.x version of DNN.  Right before they moved the core to CSharp.   All of my code is written in CSharp.  So my code can reference the core without any trouble.  This is because each language produces its own DLL and you can’t have two DLLs reference each other because that would cause a circular reference.

When you need to have DLLs reference each other, you need to use reflection from one of the two DLLs to reference the code in the DLL that can’t be accessed directly.

Most of the articles I found on the web stop with that explanation.  Actually, most of them don’t even bother to mention that using reflection is part of the solution.  The question I spent more time trying to find the answer to than I would like is, “How do I dynamically load an assembly that is produced from an App_Code subdirectory and that will have a somewhat random name?”

Here’s the line of code  you need:

System.Reflection.Assembly.Load("App_SubCode_"+ appCodeSubDirectoryName)

This returns a System.Reflection.Assembly object and from there you can use reflection like you would anywhere else.  If you need information on how to do that, I’ve written about that on other places on this site.

Related Post

  • DotNetNuke Modules – Creating Base ModulesDotNetNuke Modules – Creating Base Modules Now that we have DotNetNuke installed into Visual Studio we can go ahead and create our first modules. Actually, creating the modules is pretty simple. But it is even easier to do it wrong, which...
  • Reflection From a DLL and SerializationReflection From a DLL and Serialization Last week, we finished up our main series on reflection.  For most people, what we covered is all they will ever need.  However, there are a few other things I've needed to know due mainl...
  • Dave’s Top Programming ResourcesDave’s Top Programming Resources This isn't going to be a top ten list.  I don't think I have ten programming resources that I use on a regular basis.  Instead let's just call this Dave's Top Programming Resources that D...
  • VB.NET and CSharp RefactoringVB.NET and CSharp Refactoring I sent out the following tweet last week: “Where’s the refactor menu option?!  Oh, wait.  This is VB.NET, they don’t have that feature.” Almost immediately, I got responses.  Th...
  • DotNetNuke Modules – Finding The Page a Module is OnDotNetNuke Modules – Finding The Page a Module is On Last week we talked a bit about Inter Module Communication, the ability of one module to notify another module on the page that something needs to happen without requiring a post back.  The other ...
  • Pingback: Dew Drop – July 25, 2011 | Alvin Ashcraft's Morning Dew

  • http://www.otleyrunfancydress.co.uk Erin

    Im really hoping that more than this simple fix will be found in 6.0, so annoying that we have to look for a manual fix :(

    • Dave

      Maybe it wasn’t clear in the article, but this isn’t a DNN issue. It is an ASP.NET issue. What will change in DNN 6.0 is that the core code will already be in CSharp so those of us using CSharp won’t see this issue any more. But the VB.NET people will start to see it for the same reasons.

  • Albin Sunnanbo

    Reflection seems to be overkill here.
    The circular dependency is a code smell, however sometimes it can not be avoided. If a circular dependency is requires, create an interface in a third assembly (using your favorite language) that exposes all required callback functionality.
    If you have ClassA in AssemblyA and ClassB in AssemblyB, create in interface InterfaceA and implement that in ClassA. Then create a method or constructor in ClassB that takes InterfaceA as a paramater, like

    private readonly InterfaceA classA
    public ClassB(InterfaceA classA)
    {
    this.classA = classA;
    }

    Initialize ClassB from ClassA passing this as the InterfaceA parameter
    Then you can callback to ClassA from ClassB using methods on the classA variable.

  • Dave

    Albin,

    I am sure there are times when creating an interface would do the trick. And under other circumstances, I might implement that kind of solution. However, I think you misunderstand the issue.

    The code wasn’t issuing a callback to the object that created it, although I can see how a quick read might make you think that was the issue. The initial call was to CSharp code from VB.NET code. The CSharp code then went on to call OTHER VB.NET code. Since the VB.NET code was the primary code in this system, the VB.NET code could not instantiate the CSharp code directly. So, with an Interface solution, I would still have to use reflection to instantiate the CSharp object from my VB code and assign it to the variable declared as the Interface’s type.

    Once you’ve written that code, you might as well just write the code to dynamically call the method. It’s only one method that needed to get called in this case. If I had many of these calls to make, I might go to the effort of creating an Interface.

    Having said all that, a better solution would have been to make my CSharp code a pre-compiled DLL rather than compile at runtime code in the app_code directory. Once this is done, VB.NET no longer would care what language the code was originally written in and it could be called directly. This is, in fact, how I am currently writing my DNN code.