首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >动态加载.Net程序集的二进制序列化

动态加载.Net程序集的二进制序列化
EN

Stack Overflow用户
提问于 2013-09-18 20:22:00
回答 3查看 1.7K关注 0票数 9

我将类的一个实例序列化为一个文件(使用BinaryFormatter)

之后,在另一个项目中,我想反序列化这个文件,但是它没有工作,因为我的新项目没有我以前的类的描述。.Deserialize()得到一个异常

代码语言:javascript
运行
复制
Unable to find assembly '*MyAssembly, Version=1.9.0.0, Culture=neutral, PublicKeyToken=null'.*".

但是,我有程序集的.DLL,其中包含了我想反序列化的旧类的描述。

我不想在项目中添加引用这个DLL (我希望能够反序列化任何类型的程序集.)

如何通知序列化程序/反序列化程序使用动态加载的程序集?

EN

Stack Overflow用户

发布于 2019-12-10 21:19:24

假设您是通过Assembly.Load()Assembly.LoadFrom()加载程序集,然后按照这个答案 to https://stackoverflow.com/q/9162279/3744182 by 克里斯·肖恩中的解释,您可以在反序列化期间使用AppDomain.AssemblyResolve事件加载动态程序集。但是,出于安全原因,您将希望防止加载完全出乎意料的程序集。

一项可能的执行办法是采用以下措施:

代码语言:javascript
运行
复制
public class AssemblyResolver
{
    readonly string assemblyFullPath;
    readonly AssemblyName assemblyName;

    public AssemblyResolver(string assemblyName, string assemblyFullPath)
    {
        // You might want to validate here that assemblyPath really is an absolute not relative path.
        // See e.g. https://stackoverflow.com/questions/5565029/check-if-full-path-given
        this.assemblyFullPath = assemblyFullPath;
        this.assemblyName = new AssemblyName(assemblyName);
    }

    public ResolveEventHandler AssemblyResolve
    {
        get
        {
            return (o, a) =>
                {
                    var name = new AssemblyName(a.Name);
                    if (name.Name == assemblyName.Name) // Check only the name if you want to ignore version.  Otherwise you can just check string equality.
                        return Assembly.LoadFrom(assemblyFullPath);
                    return null;
                };
        }
    }
}

然后,在启动的某个地方,向AppDomain.CurrentDomain.AssemblyResolve添加一个适当的AppDomain.CurrentDomain.AssemblyResolve,例如:

代码语言:javascript
运行
复制
class Program
{
    const string assemblyFullPath = @"C:\Full-path-to-my-assembly\MyAssembly.dll";
    const string assemblyName = @"MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";

    static Program()
    {
        AppDomain.CurrentDomain.AssemblyResolve += new AssemblyResolver(assemblyName, assemblyFullPath).AssemblyResolve;
    }

ResolveEventHandler检查请求的程序集是否具有动态程序集的名称,如果有,则从预期的完整路径加载当前版本。

另一种选择是编写自定义SerializationBinder并将其附加到BinaryFormatter.Binder。在BindToType (string assemblyName, string typeName)中,绑定程序需要检查属于动态程序集的类型,并将它们适当地绑定到它们。这里的诀窍是处理动态加载的类型嵌套在来自另一个程序集的泛型中的情况,例如List<MyClass>。在这种情况下,assemblyName将是List<T>而不是MyClass的程序集的名称。有关如何执行此操作的详细信息,请参阅

评论 @sgnsajgon问询中,我想知道为什么我不能像在项目中显式引用签名程序集时那样反序列化流--只有formatter.Deserialize(stream)而没有其他东西。

虽然我不知道微软员工在设计这些类(回到.Net 1.1中)时在想什么,但这可能是因为:

顺便提一下,https://stackoverflow.com/q/703073/3744182对使用BinaryFormatter可能遇到的其他问题提供了有用的概述。

票数 5
EN
查看全部 3 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18881659

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档