反序列化具有在 AssemblyResolve 上加载的其他程序集中声明的类型字段的对象时出错
我有一个应用程序,它在自身内部嵌入(通过 BuildAction:嵌入式资源)引用的程序集(称为 ClassLibrary1)并将其加载到 AppDomain.CurrentDomain.AssemblyResolve 事件上。 主程序集定义了一个类 Class1:
public class Class1
{
public Class2 MyField { get; set; }
}
它具有在 ClassLibrary1 中定义的 Class2 类型的属性。 Class2 的定义:
public class Class2
{
public int A { get; set; }
}
在主方法中,我创建一个新的 XmlSerializer(typeof(Class1)):
static void Main()
{
SubscribeAssemblyResolver();
MainMethod();
}
private static void MainMethod()
{
XmlSerializer xs2 = new XmlSerializer(typeof(Class1));
Class1 cl = new Class1();
}
执行程序时出现以下错误:
无法生成临时类(结果=1)。 错误 CS0012:类型“ClassLibrary1.Class2”是在未引用的程序集中定义的。您必须添加对程序集“ClassLibrary1,Version=1.0.0.0,Culture=neutral,PublicKeyToken=c06f123f2868e8c8”的引用。 错误CS0266:无法将类型“object”隐式转换为“ClassLibrary1.Class2”。存在显式转换(您是否缺少转换?)
有什么想法吗?
其余代码:
private static void SubscribeAssemblyResolver()
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}
static Dictionary<String, Assembly> _assemblies = new Dictionary<String, Assembly>(StringComparer.OrdinalIgnoreCase);
static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
return ResolveAssembly(args.Name);
}
private static Assembly ResolveAssembly(string argsName)
{
Assembly dll;
var name = "WindowsFormsApplication1.Libs." + new AssemblyName(argsName).Name + ".dll";
if (!_assemblies.TryGetValue(name, out dll))
{
Assembly res = typeof(Program).Assembly;
using (var input = res.GetManifestResourceStream(name))
{
if (input == null)
{
//TODO: log
return null;
}
Byte[] assemblyData = new Byte[input.Length];
input.Read(assemblyData, 0, assemblyData.Length);
if (null == (dll = Assembly.Load(assemblyData)))
{
//TODO: log
return null;
}
//TODO: log
_assemblies[name] = dll;
return dll;
}
}
return dll;
}
更新:创建了BUG连接站点。您还可以从那里下载示例 Visual Stuido 2010 解决方案(只需展开“详细信息”字段组)来重现它。
I have an application which embedes (via BuildAction: Embedded Resource) referenced assembly (called ClassLibrary1) inside itself and loads it on AppDomain.CurrentDomain.AssemblyResolve event.
Main assembly defines a class Class1:
public class Class1
{
public Class2 MyField { get; set; }
}
It has a property of type Class2 defined in ClassLibrary1.
Definition of Class2:
public class Class2
{
public int A { get; set; }
}
In the main method I`m creating a new XmlSerializer(typeof(Class1)):
static void Main()
{
SubscribeAssemblyResolver();
MainMethod();
}
private static void MainMethod()
{
XmlSerializer xs2 = new XmlSerializer(typeof(Class1));
Class1 cl = new Class1();
}
While executing a programm I get the following error:
Unable to generate a temporary class (result=1).
error CS0012: The type 'ClassLibrary1.Class2' is defined in an assembly that is not referenced. You must add a reference to assembly 'ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c06f123f2868e8c8'.
error CS0266: Cannot implicitly convert type 'object' to 'ClassLibrary1.Class2'. An explicit conversion exists (are you missing a cast?)
Any ideas?
The rest of the code:
private static void SubscribeAssemblyResolver()
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}
static Dictionary<String, Assembly> _assemblies = new Dictionary<String, Assembly>(StringComparer.OrdinalIgnoreCase);
static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
return ResolveAssembly(args.Name);
}
private static Assembly ResolveAssembly(string argsName)
{
Assembly dll;
var name = "WindowsFormsApplication1.Libs." + new AssemblyName(argsName).Name + ".dll";
if (!_assemblies.TryGetValue(name, out dll))
{
Assembly res = typeof(Program).Assembly;
using (var input = res.GetManifestResourceStream(name))
{
if (input == null)
{
//TODO: log
return null;
}
Byte[] assemblyData = new Byte[input.Length];
input.Read(assemblyData, 0, assemblyData.Length);
if (null == (dll = Assembly.Load(assemblyData)))
{
//TODO: log
return null;
}
//TODO: log
_assemblies[name] = dll;
return dll;
}
}
return dll;
}
UPDATE: Created a BUG on the microsoft Connect site. You can also download a sample visual stuido 2010 solution (just expand Details fieldgroup) from there to reproduce it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我通过将程序集保存在临时文件夹中解决了类似的问题
I've solved similar problem by saving assembly in temporary folder
尝试添加属性:
Try to add atribute:
就目前而言,我最终得到了两个有些糟糕的解决方案:
还有一个非常糟糕的想法:
虽然我现在必须使用第一个解决方案,但我对此不满意,因为它太受限了。
As for now I`ve ended up with two somewhat bad solutions:
And one very bad idea:
Although I had to use solution number one for now, I`m not satisfied with it, because it is too constraining.
我会尝试 XmlSerializer(Type, Type[]) 构造函数,并使用第二个参数提供 Class2 作为附加类型。我对 XmlSerializer 的经验很少,但对于 DataContractSerializer 来说,这可以解决问题。
I'd try the XmlSerializer(Type, Type[]) constructor and provide Class2 as an additional type using the second parameter. I've few experience with the XmlSerializer, but for DataContractSerializer this does the trick.