1

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

主持人

class Host : MarshalByRefObject
{
}

合同

public abstract class PluginAdapter : MarshalByRefObject
{
}

插件

class myPlugin : PluginAdapter
{
}

这三个都存在于单独的 asm 中。我们的Host会为每个插件创建一个新的AppDomain,PluginAdapter的创建如下:

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

    PluginAdapter adapter = (PluginAdapter)instHandle.Unwrap();
}

编辑data的具体类型在哪里myPlugin

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

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

合同

public interface IPlugIn  
{  
    // do stuff  
}

插件

public class PlugIn : MarshalByRefObject, IPlugIn  
{  
}

现在,如果使用抽象类作为合约,插件不能同时继承合约和 MBRO。那么,什么成为可扩展插件框架的最佳实现。即使最初我们正在为单机操作进行开发,我们是否应该继续实施远程处理?该项目预计将分布在网络上,也可能分布在 Internet 上。我们只是还没有实现 Tcp,因为我们正试图让插件框架的基础知识得到充分理解和操作。

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

4

4 回答 4

6

抽象类是更好的选择,恕我直言。这主要是因为接口更难版本化。 这篇博客文章描述了如果您不使用基类,您可能会发现自己遇到的问题。顺便说一句,这条规则不仅适用于插件。

关于你的设计...

插件不应扩展 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事件处理,三是插件示例。

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

避免这种情况的最佳方法是为未标记可序列化且不扩展 MBRO 的插件提供一个抽象基类,并且仅将您定义的原语或密封类型从插件域带回边界。

注意:项目都是 4.0 RC。你需要这个或更高版本来运行它们。否则,您将不得不手动编辑项目文件或重建它们以使它们在 b2 或 2008 中运行。

于 2010-02-25T18:02:09.807 回答
2

如果“data.EntryPoint.FullName”是完整的类型名称,上面的代码应该可以工作。

但是,如果您试图将这种类型隔离在其自己的 AppDomain 中,则在此处应小心。通过这样做data.Assembly,您会将程序集(及其类型)拉入您的 AppDomain,从而将类型加载到正在执行的 AppDomain...

于 2010-02-25T17:51:23.243 回答
1

您可能想看看MAF(托管插件框架),它是一个内置于 .NET 中的可扩展框架,用于执行插件。它与MEF (Managed Extensibility Framework)类似(并且更早) ,但在将插件保留在自己的应用程序域等方面有更多选择。

于 2010-02-26T14:54:36.610 回答
0

如果data.EntryPoint.FullName指的是具体类型myPlugin,我看不出有任何原因导致它不起作用(除非在另一个应用程序域中存在程序集加载问题,但这是一个不同的问题)。

于 2010-02-25T17:49:31.233 回答