Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to cast transparent proxy to type from AppDomain

I'm trying to create an object in an appdomain:

var type = typeof (CompiledTemplate);
var obj = (CompiledTemplate) domain.CreateInstanceAndUnwrap (
    type.Assembly.FullName, type.FullName);

However, I always get the following error:

Unable to cast transparent proxy to type 'Mono.TextTemplating.CompiledTemplate'.

I'm running on .NET 4.0, not Mono, despite what the namespace might suggest :)

As far as I know, this error happens when .NET thinks that the Type & Assembly do not exactly match in the two domains. However, when debugging, the FullName and Location are identical. Only the Assembly.Codebase property differs - in the child AppDomain its extension is uppercased to "DLL" for some reason.

I've tried adding an AssemblyResolve handler to the AppDomain, which uses Assembly.LoadFrom to load the filename explicitly, but the CodeBase's extension still gets uppercased. Since the original assembly was also loaded with Assembly.LoadFrom (via Mono.Addins), the difference between the CodeBase values seems very strange.

Any suggestions for fixing or working around this problem?

like image 395
Mikayla Hutchinson Avatar asked Sep 07 '10 03:09

Mikayla Hutchinson


2 Answers

Could you be running into an issue with assembly load contexts? (e.g. see here) You have a type that's clearly in the load context (because you're using typeof(CompiledTemplate)), but you're saying that the type in the secondary AD is loaded into the load-from context...

Did you check with fuslogvw to determine exactly what assemblies are being loaded? The fuslog trace will also tell you if the assemblies are being loaded into different contexts.

like image 86
Sasha Goldshtein Avatar answered Oct 06 '22 05:10

Sasha Goldshtein


A second copy of the assembly is, indeed, being loaded into memory as it is.

An instance of a type in the runtime is specific to the instance of the assembly loaded - so even if the same DLL file is loaded in a second time, the types are not considered to match.

This is a typical problem when "DLLHell" is extended into the "GACAndDLLHell". "GACONLYHeaven" is a better place ... :).

That the filenames are subtly different (the .DLL extension has a different case) implies that the same DLL is being loaded from two places (that is: the GAC is case-insensitive/always lower case on filenames IIRC).

An abstract class or, preferably, an interface is what you need here.

If you can't make changes to the code base I would, first, make very sure that the DLL exists in only 1 place on the drive (or 0 places on the drive if it is being loaded from the GAC). A copy of the DLL that contains the type: 'CompiledTemplate' in your app /bin folder would be a real culprit ...?

Is this new code or existing code that is now failing for some reason?

like image 20
Aidanapword Avatar answered Oct 06 '22 05:10

Aidanapword