C# 使对象保持活动状态的插件系统
我有一个应用程序,需要在运行时以.dll文件的形式加载和卸载一些插件。这些dll文件包含一个或多个派生自我的抽象类模块的类,如下所示:C# 使对象保持活动状态的插件系统,c#,dll,plugins,.net-assembly,appdomain,C#,Dll,Plugins,.net Assembly,Appdomain,我有一个应用程序,需要在运行时以.dll文件的形式加载和卸载一些插件。这些dll文件包含一个或多个派生自我的抽象类模块的类,如下所示: public abstract class Module : MarshalByRefObject { //various fields here, not reported as they are not useful to understand public abstract void Print(); } 据我所知:在C#中卸载程序集及
public abstract class Module : MarshalByRefObject
{
//various fields here, not reported as they are not useful to understand
public abstract void Print();
}
据我所知:在C#中卸载程序集及其类的唯一方法是将程序集放在专用的Appdomain中,然后在不再需要时卸载它,Appdomain之间通信的唯一方法是从MarshalByRefObject或MarshalByValueObject派生。然后,当我将模块的引用传递给另一个AppDomain时,我并没有真正得到对象,而是得到一个透明的代理。有人能确认我上面写的吗
现在真正的问题是:假设在我的文件PersonPlugin.dll中有一个扩展模块的“Person”类。此类包含字段名称、姓氏和电话号码
方法Print会定期调用(定期调用Print没有意义,但这是一个示例)打印这3个字段
后来,我用新版本的类Person构建了一个新的dll,它有一个名为address的新字段,Print method现在也打印地址。
注:插件是由第三方制作的,我不知道新版本是否与旧版本相似或完全不同,但在我的情况下,可以安全地假设一个职业人士在不同版本之间不会有太大差异
然后,我用这个新文件替换旧的dll文件(dll在专用的appdomain中被影子复制,因此该文件是可写/可删除的)
FileSystemWatcher会注意到更改,并:
关于你的第2点:没有硬性限制,为什么我不允许两个相同类型但不同版本的模块共存,只要它们在不同的名称空间或不同的DLL中,因为在我的系统中,每个模块都用不同的ID标识和引用我想你真的想玩大黄蜂的巢 有一些设计注意事项您没有提到 1) 为什么你需要一直在线。为什么你不能离线,比如说每周重启一次1小时。无论您实现什么解决方案(反射/序列化),都会给您带来性能成本,更不用说维护方面的巨大开销了 2) 有没有可能你想要相同插件的两个版本。在java世界中,有一个称为OSGI的框架。你要做的是依赖于某个模块,但在某些情况下,同一模块的两个版本可能同时在线。尤其地
public interface IModule
{
Person GetPerson();
void Print();
}
public class Person : MarshalByRefObject
{
...
}
public interface IModule
{
Person GetPerson();
void Print();
IDictionary<string, object> GetState();
void SetState(IDictionary<string, object> state);
}
public class ModuleManager : MarshalByRefObject
{
public IModule Module { get; set; }
public void Initialize(string path)
{
// Load the module
// Setup file watcher
}
public void SaveState(string file)
{
var state = this.Module.GetState();
// Write this state to a file
}
public void LoadState(string file)
{
var state = this.ReadState(file);
this.Module.SetState(state);
}
private IDictionary<string, object> ReadState(string file)
{
...
}
}