如何在没有插件接口的单独 DLL 的情况下使应用程序能够识别插件?

发布于 2024-11-11 17:19:53 字数 250 浏览 1 评论 0原文

开发插件架构的传统过程似乎是创建一个单独的 DLL,仅包含所有插件将实现的通用接口,并使核心应用程序和插件都依赖于该接口。

我正在尝试做同样的事情,但没有单独的接口 dll。一种明显的方法是让所有插件都依赖于核心应用程序,但这并不是一个很好的解决方案。

你能想出更漂亮的解决方案吗?理想情况下,不会有 dll 捆绑该接口;如果这是不可能的,那么如果不打算运行插件的用户根本不需要下载插件 dll,那就太酷了。这样,只有那些运行插件的人才需要接口 DLL。

The traditional procedure to develop a plugin architecture seems to be to create a separate DLL containing only the common interface that all plugins will implement, and make both the core app and the plugins depend on that.

I'm trying to do just the same, but without a separate interface dll. One obvious way is to make all plugins depend on the core app, but that's hardly a pretty solution.

Can you think of prettier solution? Ideally, there wouldn't be a dll bundling the interface; if that's impossible, the it would be pretty cool if a user that doesn't intend to run plugins wouldn't need to download the plugin dll at all. Taht way, only those who run plugins need the interface DLL.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

思慕 2024-11-18 17:19:53

您可以使用 MEF 并导入带有元数据(字符串)的 System.Object 实现,而不是实际的接口或定义的类型。

话虽如此,主机进程在没有已知接口的情况下将很难使用插件。需要通过反射进行某种形式的使用,这将是非常非常难看的。

就我个人而言,我只会在接口中包含一个简单的 DLL,它可以独立存在。应用程序可以将其与发行版捆绑在一起,并且插件可以使用它。这样做的好处远远超过了维护一个只有接口的小型组件的额外“成本”。

You could use MEF and import System.Object implementations with metadata (strings) instead of actual interface or defined types.

That being said, it's going to be difficult for the host process to use the plugins without a known interface. Some form of use via reflection would be required, which is going to be very, very ugly.

Personally, I would just include a simple DLL with the interfaces, which can stand alone. The application can bundle it with the distributions, and the plugins can use it. The benefits of this far outweigh the extra "cost" of maintaining a small assembly with nothing but interfaces.

山人契 2024-11-18 17:19:53

您可以加载程序集并通过反射访问其类型。这里有一些示例: http://www.csharp-examples.net/reflection-examples/ ,我提取了一些更有趣的内容:

Assembly testAssembly = Assembly.LoadFile(@"c:\Test.dll");
Type calcType = testAssembly.GetType("Test.Calculator");
object calcInstance = Activator.CreateInstance(calcType);

// Get property value
PropertyInfo numberPropertyInfo = calcType.GetProperty("Number");
double value = (double)numberPropertyInfo.GetValue(calcInstance, null);

....

// invoke public instance method: public void Clear()
calcType.InvokeMember("Clear",
     BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public,
     null, calcInstance, null);

您可以强制要求以某种方式编写插件,以便您知道要实例化哪些类以及要调用哪些方法,等等。本质上,是通过文档而不是代码来表达的非正式接口。

现在,这不是实现插件架构的好方法,因为在编写插件时会丢失大量编译时检查,并且一般来说,最好承担部署额外 DLL 的麻烦。

You could load the assembly and access its types through Reflection. There are some examples here: http://www.csharp-examples.net/reflection-examples/, and I've extracted some of the more interesting ones:

Assembly testAssembly = Assembly.LoadFile(@"c:\Test.dll");
Type calcType = testAssembly.GetType("Test.Calculator");
object calcInstance = Activator.CreateInstance(calcType);

// Get property value
PropertyInfo numberPropertyInfo = calcType.GetProperty("Number");
double value = (double)numberPropertyInfo.GetValue(calcInstance, null);

....

// invoke public instance method: public void Clear()
calcType.InvokeMember("Clear",
     BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public,
     null, calcInstance, null);

You can mandate that plugins are written in certain ways so that you know which classes to instantiate and which methods to call, and so on. Essentially, an informal interface that is expressed via documentation rather than through code.

Now, this is not a good way to implement a plugin architecture, because you lose a lot of compile-time checking when writing plugins, and generally speaking it's better to take the hit of deploying the extra DLL.

⊕婉儿 2024-11-18 17:19:53

实现此目的的一种方法是通过反射。您需要检查加载的(插件)程序集以提取方法信息并调用 Invoke。

在 .NET 4 中实现此目的的另一种方法是通过动态。动态关键字允许您绕过编译时类型检查,因此您可以调用任何您想要的方法,并且它将在运行时绑定。

这两个选项都会对性能产生影响,因此如果主机和插件之间有很多对话,您可能不想这样做。

One way to accomplish this is via Reflection. You would need to inspect the loaded (plugin) assembly to pull out the method information and call Invoke.

Another way to accomplish this in .NET 4 is via dynamic. The dynamic keyword allows you to bypass compile-time type checking so you can call any method you want and it will be bound at run-time.

Both options have performance implications, so you would probably not want to do this if you're going to have a lot of chatter between the host and the plugins.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文