二进制序列化重新加载DLL类

时间:2012-12-19 22:35:47

标签: c# serialization dll

我正在尝试制作一个棋盘游戏框架,在每个游戏中加载它们自己的插件类(通过依赖注入)。然后每个“游戏”都是它自己的DLL。因此,插件处理正确的资源加载游戏中的“pawn”,游戏板的正确图像,游戏需要的任何特殊逻辑等。

我建议的文件夹结构是

game.exe
plugins/
    /plugin1
        /textures
        plugin1.dll

    /plugin2
        /textures
        plugin2.dll

当你开始游戏时,我让你使用文件管理器来加载正确的dll(将来会被改进),并且当其他客户端连接到你时,它会让他们加载插件,或者失败如果你还没有这个游戏的dll,那就连接。

加载代码示例如下:

Assembly assembly = Assembly.LoadFile(openPlugin.FileName);

string fullTypeName = "TestPlugin.TestPlugin";
Type dllType = assembly.GetType(fullTypeName);
IPlugin myType = (IPlugin)Activator.CreateInstance(dllType);

我现在正在使用硬编码字符串作为类型名称,但最终会改变。

为了与其他人一起玩,有一种网络架构主要包括使用对象的二进制序列化。问题是当我反序列化插件dll中的类的对象时,系统想要从文件重新加载dll。当它试图重新加载它时,它遵循正常规则并在exe目录中查找dll(如果我将插件dll移动到主目录,这一切都有效)。

以下是二进制序列化的示例(如果有帮助)

public Stream SerializeObject(object obj)
{
    Stream stream = new MemoryStream();

    BinaryFormatter formatter = new BinaryFormatter();

    formatter.Serialize(stream, obj);

    return stream;
}

/// <summary>
/// Deserializes Objects
/// </summary>
/// <param name="stream">Stream containing the binary objects</param>
public T DeserializeObject<T>(byte[] data)
{
    Stream stream = new MemoryStream(data);
    IRemotingFormatter formatter = new BinaryFormatter();

    return (T)formatter.Deserialize(stream);
}

我希望我可以减少开放性,但我能做些什么来解决这个并保留我想要的目录结构? - 制作某种形式的自定义加载器,通过插件递归搜索? - 为二进制序列化选择不同的方法? - 当我'加载'时,我是不是正确地将该类加载到'内存'以供将来使用?

如果你读到这篇文章并且去'为什么他这样做那么?',我欢迎你进行建筑改变? :)

1 个答案:

答案 0 :(得分:0)

1)使用Assembly assembly = Assembly.LoadFrom("dllPath");代替Assembly.LoadFile()

2)由于你的插件有不同的名称,你可以将它们放在一个目录中,并在app.config中定义到这个目录的路径。

3)在主AppDomain以外的地方加载Dll可能是个好主意,这样你就可以在不重启应用程序的情况下卸载它们,请参阅我的示例here