Хорошо. Я только что столкнулся с этой же проблемой.
В моем случае проблема заключалась в том, что я загружал сборку из байтового массива (я использую модель плагина, так что это довольно распространенное использование) и десериализовал объект, но он не был приведен с тем же сообщение как исходный вопрос.
Сначала я подумал, что это только из-за сериализатора и dll-версий и тому подобного ... поэтому я написал свой собственный сериализатор и снова столкнулся с той же проблемой.
Проблема действительно возникла из-за создания типа. В моих процедурах десериализации я использовал знакомый метод Type.GetType (string) и передавал AssemblyQualifiedName, который работает и для всех типов, которые находятся за пределами mscorlib, это требуется.
Что ж, получается, что GetType не просматривает список загруженных сборок, чтобы попытаться найти совпадение, но оставляет его на усмотрение Fusion.
Это означает, что любой тип, который существует в сборке, которая была загружена в любом контексте, кроме «Загрузить» (иначе «По умолчанию» в сообщении об исключении), не найден, и GetType пытается загрузить сборку обычным образом.
В моем случае это привело к загрузке 2 экземпляров сборки в домене приложения: из моего байтового массива, а другой - с диска, найденного с помощью fusion.
Я решил эту проблему путем перечисления загруженных сборок в моем домене приложения и поиска подходящего имени сборки (проанализированного из моего AssemblyQualifiedName). Найдя его, я создал свой тип (без информации о сборке), используя эту конкретную сборку (Assembly.GetType (String)).
Вот код, который позволил мне преодолеть эту проблему:
Dim ot As System.Type
Dim tname = "MyType"
Dim aname = "MyPlugin"
'// The following lambda expression returns only assemblies that match my assembly name
'// Your assembly name could be a fully qualified name or just the simple assembly name
'// I chose to use the simple name so that i didn't have to store unnecessary data and because i didn't want version specific info
Dim asms = AppDomain.CurrentDomain.GetAssemblies().Where(Function(__) __.GetName.Name.Equals(aname))
'If there is only one assembly loaded...use it
If asms.Count = 1 Then
ot = asms(0).GetType(tname)
'// If there are multiple assemblies loaded (with the same name), i'm picking the one that is loaded from disk, if such is available, otherwise default back to the first one that was loaded into the appdomain
'// If you do have multiple assemblies loaded, it's because you (or .NET) has loaded them in different contexts. You might need to adjust for which context you want. I suppose you could pass the desired context in as a parameter and look for it
ElseIf asms.Count > 1 Then
Dim asm = asms.FirstOrDefault(Function(__) Not String.IsNullOrEmpty(__.Location))
If asm IsNot Nothing Then
ot = asm.GetType(tname)
Else
ot = asms(0).GetType(tname)
End If
Else
'// not yet loaded...use default type resolution from Type.GetType
ot = Type.GetType(tname & "," & aname)
End If
Dim obj
'// Note that the method here is using the already resolved System.Type from above.
'// This is important because it causes Activator to create an instance from the assembly
'// that we really want and not one from fusion's resolver.
obj = Activator.CreateInstance(ot)
Надеюсь, это поможет кому-то еще.
-Eriq