tags:

views:

1453

answers:

4

I'm trying to load assemblies in a separate app domain, but am running into a very strange problem. Here's some code:

    public static void LoadAssembly(string assemblyPath)
    {

        string pathToDll = Assembly.GetCallingAssembly().CodeBase;
        AppDomainSetup domainSetup = new AppDomainSetup
        {
            PrivateBinPath = pathToDll
        };

        AppDomain newDomain = AppDomain.CreateDomain("AssemblyLoader",null,domainSetup);


        AssemblyLoader loader = (AssemblyLoader)newDomain.CreateInstanceFromAndUnwrap(
            pathToDll,
            typeof(AssemblyLoader).FullName);

    }

AssemblyLoader is another class in the same assembly as this one, and it inherits from MarshalByRef, however for some strange reason, I get a cast exception every time I try to run this. I even hardcoded the path to the DLL instead of using GetCallingAssembly().CodeBase yet I keep getting this exception.

I understand it's hard to answer a question like this without actually seeing it and having more information, but maybe someone has run into a similar situation and would know the common "gotchas" and what I should look out for.

EDIT: The reason I don't want to load it directly is because this is just part of the code. The ultimate goal is that this class will have a method that load assemblies, gets their GUID and some other info about them and stores them in a database for a project I'm working on. Therefore, if I load this assembly in a separate app domain, I can load the others there too and then unload the app domain. No point in having all these assemblies loaded for the duration of the app, if I only need that data.

A: 

I don't believe the PrivateBinPath configuration is necessary, beyond that you don't need to use the Path to the DLL, but rather the Assembly's fully qualified name for the first parameter; try:

AssemblyLoader loader = (AssemblyLoader)newDomain.CreateInstanceFromAndUnwrap(
        typeof(AssemblyLoader).Assembly.FullName,
        typeof(AssemblyLoader).FullName);
TheXenocide
Wrong answer. CreateInstanceFromAndUnwrap()'s first parameter is a path and filename, not an assembly name. CreateInstanceAndUnwrap()'s, however, is an assembly name, but that doesn't help the asker because it would just resolve to the same path and filename.
Timwi
http://msdn.microsoft.com/en-us/library/y7h7t2a2.aspx
TheXenocide
+1  A: 

(EDIT: after reading the exception given, changing answer completely)

It appears the problem is the CreateInstanceFromAndUnwrap call, which uses the LoadFrom semantics of 'pathToDll'. Suzanne Cook detailed the possible sticking point on her blog where your original AppDomain tries to call Load("SomeAssembly, [...]") as opposed to LoadFrom("pathToDll") when trying to resolve the type in question.

Her advice was to hook the AssemblyResolve event on the current domain to do the correct LoadFrom in order to get the type. A little bit of targetted googling brings up a possible solution to the problem based on Suzanne's suggestion.

sixlettervariables
No, here's what it's saying:Unable to cast transparent proxy to type 'CompanyNamespaceTakenOut.AssemblyLoader
BFree
Updated to reflect that.
sixlettervariables
A: 

There's a lot of good information for what you're trying to do here: http://stackoverflow.com/questions/225330/how-to-load-a-net-assembly-for-reflection-operations-and-subsequently-unload-it

Joseph Daigle
A: 

Check out this article.

Using the code in that article I got a cross app-domain object. I abstracted things a bit with generics and have three assemblies. (i.e. 1 defining the interface, 1 defining the plugin implementation, and the main program which tells the generic what to load.) The original articles code is easy to follow.

Jason D