问题
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?
回答1:
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.
回答2:
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?
回答3:
Perhaps you can use the dynamic keyword instead of casting it to a specific type:
var type = typeof (CompiledTemplate);
dynamic obj = domain.CreateInstanceAndUnwrap (
type.Assembly.FullName, type.FullName);
That might at least give you a workaround to the problem. Of course, the potential drawbacks will be not having compile time checking and/or slower performance. However, these might be negligible trade-offs depending on your situation.
回答4:
I have a WCF net named pipes application that uses a callback (duplex) architecture.
I got this error because my service interface's [ServiceContract]
was annotated with the wrong callback.
来源:https://stackoverflow.com/questions/3655484/unable-to-cast-transparent-proxy-to-type-from-appdomain