使用抽象类作为插件框架中的契约

IAb*_*act 1 c# plugins marshalbyrefobject .net-3.5

抽象类可以用作"主机"和"插件"之间的契约对象吗?这个想法是插件继承了契约(我们称之为适配器).我们也理解框架中的所有参与者都必须继承MarshalByRefObject(MBRO).所以,这就是我们的想法 -

主持人:

class Host : MarshalByRefObject
{
}
Run Code Online (Sandbox Code Playgroud)

合同:

public abstract class PluginAdapter : MarshalByRefObject
{
}
Run Code Online (Sandbox Code Playgroud)

插件:

class myPlugin : PluginAdapter
{
}
Run Code Online (Sandbox Code Playgroud)

这三个都存在于不同的asm中.我们的主机将为每个插件创建一个新的AppDomain,并按如下方式创建PluginAdapter:

{
    ObjectHandle instHandle = Activator.CreateInstance(
    newDomain, data.Assembly.FullName, data.EntryPoint.FullName);

    PluginAdapter adapter = (PluginAdapter)instHandle.Unwrap();
}
Run Code Online (Sandbox Code Playgroud)

编辑:data具体类型在哪里myPlugin.

我们想知道该框架的实施是否有效.我们已经看到使用接口(IPlugin)进行插件派生的文章,以及作为契约的具体类.这些文章还会说可以使用抽象类,但没有给出该实现的示例.是否要求合同是具体的类?

编辑:在Richard Blewett的这个例子中 - C#Reflection - 他使用了一个更简单的实现:

合同:

public interface IPlugIn  
{  
    // do stuff  
}
Run Code Online (Sandbox Code Playgroud)

插件:

public class PlugIn : MarshalByRefObject, IPlugIn  
{  
}
Run Code Online (Sandbox Code Playgroud)

现在,如果使用抽象类作为契约,则插件不能继承合同和MBRO.那么,什么成为可扩展插件框架的最佳实现.我们是否应该继续实施远程操作,尽管最初我们正在开发单机操作?该项目预计将分布在整个网络中,也可能跨越互联网.我们还没有实现Tcp,因为我们正在努力让插件框架的基础知识得到充分理解和操作.

使用环回在单台机器上实现Tcp远程处理是否有意义?

小智 6

imho,抽象类是更好的选择.它主要是因为接口更难以版本化. 此博客文章描述了如果您不使用基类,您可能会遇到的问题.这个规则不仅适用于插件,顺便说一下.

关于你的设计......

插件不应该扩展MBRO.您应该使用您的主机(应该扩展MBRO)来对您的插件进行所有调用,包括处理插件事件.如果您尝试将插件DLL拉到并使用其代理,则很容易无意中将插件DLL加载到您的主应用程序域中.

例如,如果插件为其中一个方法返回IEnumerable,它可能会返回插件程序集中定义的IEnumerable实现.如果这不扩展MBRO,主appdomain将必须加载插件程序集.


我在这里上传了三个处理appdomains的项目:

http://cid-f8be9de57b85cc35.skydrive.live.com/self.aspx/Public/NET%20AppDomain%20Tests/appdomaintests.zip

一个是在appdomains中使用回调,第二个是跨appdomain事件处理,第三个是插件示例.

在插件示例中,应用程序定义了一个插件接口(它是一个演示,而不是最佳实践!)和一个插件主机.该应用程序从磁盘加载一个插件程序集raw,并通过插件主机代理将其传递到插件appdomain,然后加载它.插件主机然后实例化插件并使用它.但是当主机将插件程序集中定义的类型返回到应用程序appdomain时,插件程序集将加载到主应用程序域中,从而使整个插件变得毫无意义.

最好避免这种情况是为插件提供一个抽象基类,它没有标记为可序列化并且不扩展MBRO,并且只返回您从插件域跨越边界定义的基元或密封类型.

注意:项目都是4.0 RC.你需要这个或更多才能运行它们.否则,您必须手动编辑项目文件或重建它们以使它们在b2或2008中运行.