简体   繁体   English

消息在插件框架中传递

[英]Message passing in a plug-in framework

First off, there's a bit of background to this issue available on my blog: 首先,我的博客上有一些关于这个问题的背景知识:

I'm aware that the descriptions aren't hugely clear, so I'll try to summarise what I'm attempting as best I can here. 我知道这些描述并不是很清楚,所以我会试着总结一下我在这里能做的最好的事情。 The application is a personal finance program. 该申请是个人理财计划。 Further background on the framework itself is available at the end of this post. 关于框架本身的进一步背景可在本文末尾找到。

There are a number of different types of plug-in that the framework can handle (eg, accounts, export, reporting, etc.). 框架可以处理许多不同类型的插件(例如,帐户,导出,报告等)。 However, I'm focussing on one particular class of plug-in, so-called data plug-ins, as it is this class that is causing me problems. 但是,我专注于一个特定类型的插件,即所谓的数据插件,因为正是这个类导致了我的问题。 I have one class of data plug-in for accounts, one for transactions, etc. 我有一类帐户数据插件,一个用于交易等。

I'm midway through a vast re-factoring that has left me with the following architecture for data plug-ins: 我正处于一个巨大的重新分解的中途,这使我得到了以下数据插件架构:

  • The data plug-in object (implementing intialisation, installation and plug-in metadata) [implements IDataPlugin<FactoryType> ] 数据插件对象(实现初始化,安装和插件元数据)[实现IDataPlugin<FactoryType> ]
  • The data object (such as an account) [implements, eg, IAccount ] 数据对象(例如帐户)[实现,例如, IAccount ]
  • A factory to create instances of the data object [implements, eg, IAccountFactory ] 用于创建数据对象实例的工厂[实现,例如, IAccountFactory ]

Previously the data object and the plug-in object were combined into one, but this meant that a new transaction plug-in had to be instantiated for each transaction recorded in the account which caused a number of problems. 以前,数据对象和插件对象合并为一个,但这意味着必须为帐户中记录的每个事务实例化一个新的事务插件,这会导致许多问题。 Unfortunately, that re-factoring has broken my message passing. 不幸的是,重新分解已经打破了我的信息传递。 The data object implements INotifyPropertyChanged , and so I've hit a new problem, and one that I'm not sure how to work around: the plug-in object is registering events with the message broker, but it's the data objects that actually fire the events. 数据对象实现了INotifyPropertyChanged ,所以我遇到了一个新问题,而且我不知道如何解决这个问题:插件对象正在使用消息代理注册事件,但它实际上是触发的数据对象事件。 This means that the subscribing plug-in currently has to subscribe to each created account, transaction, etc.! 这意味着订阅插件当前必须订阅每个创建的帐户,交易等! This is clearly not scalable. 这显然是不可扩展的。

As far as I can tell at the moment I have two possible solutions: 据我所知,目前我有两种可能的解决方案:

  1. Make the data plug-in object a go-between for the data-objects and message broker, possibly batching change notifications. 使数据插件对象成为数据对象和消息代理的中间人,可能是批量更改通知。 I don't like this because it adds another layer of complexity to the messaging system that I feel I should be able to do without. 我不喜欢这个,因为它为消息传递系统增加了另一层复杂性,我觉得我应该可以不用。
  2. Junk the current event-based implementation and use something else that's more easily manageable (in-memory WCF?!). 垃圾当前基于事件的实现并使用其他更易于管理的内容(内存中的WCF ?!)。

So I guess I'm really asking: 所以我想我真的在问:

  1. How would you solve this problem? 你会如何解决这个问题?
  2. What potential solutions do you think I've overlooked? 您认为我忽略了哪些潜在的解决方案?
  3. Is my approach even vaguely on-track/sensible?! 我的方法是否模糊地在轨道/合理?! :-) :-)

As you will be able to tell from the dates of the blog posts, some variant of this problem has been taxing me for quite a long time now! 正如你可以从博客文章的日期中看出来的那样,这个问题的一些变体已经给我带来了很长一段时间了! As such, any and all responses will be greatly appreciated. 因此,我们将非常感谢任何和所有回复。

The background to the framework itself is as follows: 框架本身的背景如下:

My plug-in framework consists of three main components: a plug-in broker, a preferences manager and a message broker. 我的插件框架包含三个主要组件:插件代理,首选项管理器和消息代理。 The plug-in broker does the bread-and-butter plug-in stuff: discovering and creating plug-ins. 插件代理实现了面包和插件的功能:发现和创建插件。 The preferences manager manages user preferences for the framework and individual plug-ins, such as which plug-ins are enabled, where data should be saved, etc. Communication is via publish/subscribe, with the message broker sitting in the middle, gathering all published message types and managing subscriptions. 首选项管理器管理框架和各个插件的用户首选项,例如启用哪些插件,应保存数据等。通过发布/订阅进行通信,消息代理位于中间,收集所有已发布的消息类型和管理订阅。 The publish/subscribe is currently implemented via the .NET INotifyPropertyChanged interface, which provides one event called PropertyChanged ; 发布/订阅目前通过.NET INotifyPropertyChanged接口实现,该接口提供一个名为PropertyChanged事件; the message broker builds a list of all plug-ins implementing INotifyPropertyChanged and subscribes other plug-ins this event. 消息代理构建一个实现INotifyPropertyChanged的所有插件的列表,并为此事件订阅其他插件。 The purpose of the message passing is to allow the account and transaction plug-ins to notify the storage plug-ins that data has changed so that it may be saved. 消息传递的目的是允许帐户和事务插件通知存储插件数据已更改,以便可以保存它。

Wow! 哇! Big question! 大问题! :) :)

Correct me if I'm wrong. 如果我错了纠正我。 Your basic solution now is kind of an Observer pattern, where the data object (Account, etc) notifies about changes in their states. 您现在的基本解决方案是一种Observer模式,其中数据对象(Account等)通知其状态的变化。 You think that the problem is that the subscribing plugin has to register in every object to be able to handle notifications. 您认为问题在于订阅插件必须在每个对象中注册才能处理通知。

That's not a problem per se, you can put the event control in the Domain Model , but I suggest you create a Service Layer and do this event notifications in this layer. 这本身不是问题,您可以将事件控件放在域模型中 ,但我建议您创建一个服务层并在此层中执行此事件通知。 That way just one object would be responsible for publishing notifications. 这样,只有一个对象负责发布通知。

Martin Fowler have a series of Event Patterns in his blog. Martin Fowler在他的博客中有一系列的活动模式。 Check it out ! 看看吧 Very good reading. 非常好的阅读。

This is my understanding of your question: You have a plugin object that may have to listen for events on x data objects - you don't want to subscribe to the event on each data object though. 这是我对您的问题的理解:您有一个插件对象,可能必须侦听x数据对象上的事件 - 您不希望在每个数据对象上订阅事件。 I'm assuming that several plugins may want to listen to events on the same data object. 我假设有几个插件可能想要监听同一数据对象上的事件。

You could create a session type object. 您可以创建会话类型对象。 Each plugin listens for events on the session object. 每个插件都会侦听会话对象上的事件。 The data object no longer raises the event - it calls the session object to raise the event (one of the parameters would have to be the data object raising the event). 数据对象不再引发事件 - 它调用会话对象来引发事件(其中一个参数必须是引发事件的数据对象)。

That means that your plugins only have to subscribe to one event, but they get the event from all data objects. 这意味着您的插件只需订阅一个事件,但它们从所有数据对象获取事件。

On the other hand, if only one plugin will ever listen to a data object at a time, why not just have the data object call the plugin directly? 另一方面,如果一次只有一个插件会监听数据对象,为什么不直接让数据对象调用插件呢?

现在还早,但您是否考虑过尝试使用MEF而不是自己动手?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM