dmck
dmck

Reputation: 7861

Marshalling .NET Object when class is in another namespace

I am having a problem with Marshalling an object across application domains in a .NET Windows Service.

I have created two app's that marshal an object across an app domain and run code through a proxy MarshalByRefObject

The first application was a simple proof of concept since I do not have a lot of experience with marshalling across application domains. It contains a single project where the MarshalByRefObject is defined in the same namespace as the rest of the project. This app works fine, using almost the same code as my other app. The main difference is that the class I am Marshalling in the second app is defined in another Namespace.

The other project is more complex, it is a Windows Service with multiple projects. The main Windows Service loads a library that that does the marshalling. The class type of the Marshal target type is defined in another library, so I use the fully qualified namespace/class name.

The problem I am facing is that when it gets to the last line of the code below it throws an exception:

Could not load CompanyName.ProductGroup.BusinessObjects.ProductName.MarshalByRefScriptCompiler from assembly ProductNameService where product name is the main Windows Service class.

The Code:

AppDomain compilerDomain = null;
AppDomainSetup compilerDomainSetup;
CompanyName.ProductGroup.BusinessObjects.ProductName.MarshalByRefScriptCompiler scriptCompiler;

...

// Setup a seperate AppDomain 
compilerDomainSetup = new AppDomainSetup();
exeAssembly = Assembly.GetEntryAssembly().FullName;
compilerDomainSetup.ApplicationBase = System.Environment.CurrentDirectory;

compilerDomainSetup.DisallowBindingRedirects = false;
compilerDomainSetup.DisallowCodeDownload = true;
compilerDomainSetup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
compilerDomain = AppDomain.CreateDomain("LiveLinkCSScriptDomain", null, compilerDomainSetup);

// Create an instance of the MarshalByRefScriptCompiler in the other AppDomain
scriptCompiler = (CompanyName.ProductGroup.BusinessObjects.ProductName.MarshalByRefScriptCompiler)compilerDomain.CreateInstanceAndUnwrap(exeAssembly, typeof(CompanyName.ProductGroup.BusinessObjects.ProductName.MarshalByRefScriptCompiler).FullName);

I have done research on this exception and almost everything I find says that it is a problem with versioning of the DLL, however my DLL's are not in the GAC, and there are no other versions installed. I am doing a clean build and installing the service with installutil.

I used the MSDN documentation as a guide for creating the code that does the marshalling

I am wondering if there is an issue with loading the MarshalByRefScriptCompiler because the type is in another library. I am able to create a MarshalByRefScriptCompiler in a simple winforms app, but I get the exception in my windows service.

Any tips or insight would be greatly appreciated!

Upvotes: 1

Views: 1241

Answers (2)

Russell McClure
Russell McClure

Reputation: 4851

I should be able to help you. I've spent many hours recently (How do I pass references as method parameters across AppDomains?) working on different cross appdomain marshaling problems. My first suggestion would be to try using CreateInstanceFromAndUnwrap instead of CreateInstanceAndUnwrap.

I'm also a little wary of this line:

compilerDomainSetup.ApplicationBase = System.Environment.CurrentDirectory;

How is your original AppDomain being created? Are you hosted in IIS, in which case your original AppDomain will be using ShadowCopy? Are all the dlls involved in a single folder?

EDIT:

To summarize, you can use CreateInstanceAndUnwrap if your compilerDomainSetup.ApplicationBase is set to the directory containing your dll and you pass in the correct first param (e.g. typeof(MarshalByRefScriptCompiler).Assembly.FullName).

Or, you can use CreateInstanceFromAndUnwrap and just pass in the location (e.g. typeof(MarshalByRefScriptCompiler).Assembly.Location) of the containing assembly as the first param.

Upvotes: 2

Chris Stavropoulos
Chris Stavropoulos

Reputation: 1778

As a starting point, you could try Process Monitor to determine where it's trying to load your missing type from. It's very possible that it's as simple as it looking in the wrong directory for your assembly.

Upvotes: 1

Related Questions