我有一个可由用户配置的数据库应用程序 - 其中一些选项是从不同的外部插件系统中选择的。
我有一个基本插件类型,我的数据库架构具有相同的插件记录类型和相同的字段。我必须PlugingMananger
在应用程序启动时加载插件(通过 IoC 容器)并将它们链接到数据库(基本上将磁盘上的插件字段复制到数据库)。
public interface IPlugin
{
Guid Id{ get; }
Version Version { get; }
string Name { get; }
string Description { get; }
}
然后可以使用 检索插件PlugingMananger.GetPlugin(Guid pluginId, Guid userId)
,其中用户 ID 是可能调用插件操作的多个用户之一的用户 ID。
应用程序已经预先声明了一组已知接口,每个接口都特定于某个功能(格式化程序、外部数据、数据发送器等),如果插件实现了一个未知的服务接口,那么它将被忽略:
public interface IAccountsPlugin : IPlugin
{
IEnumerable<SyncDto> GetData();
bool Init();
bool Shutdown();
}
插件还可以PluginSettingAttribute
在多用户系统中为每个用户定义设置属性 - 这些属性是在为特定用户检索插件时设置的,而PluginPropertyAttribute
对于所有用户通用且插件一次只读设置的属性在应用程序启动时注册插件时。
public class ExternalDataConnector : IAccountsPlugin
{
public IEnumerable<AccountSyncDto> GetData() { return null; }
public void Init() { }
public void Shutdown() { }
private string ExternalSystemUsername;
// PluginSettingAttribute will create a row in the settings table, settingId
// will be set to provided constructor parameter. this field will be written to
// when a plugin is retrieved by the plugin manager with the value for the
// requesting user that was retrieved from the database.
[PluginSetting("ExternalSystemUsernameSettingName")]
public string ExternalSystemUsername
{
get { return ExternalSystemUsername }
set { ExternalSystemUsername = value; }
}
// PluginPropertyAttribute will create a row in the attributes table common for all users
[PluginProperty("ShortCodeName")]
public string ShortCode
{
get { return "externaldata"; }
}
public Version PluginVersion
{
get { return new Version(1, 0, 0, 0); }
}
public string PluginName
{
get { return "Data connector"; }
}
public string PluginDescription
{
get { return "Connector for collecting data"; }
}
}
以下是我寻求指导的问题和领域:
通过上述将 IoC 容器中的插件链接到数据库的抽象,用户可以选择数据库字段
Customer.ExternalAccountsPlugin = idOfExternalPlugin
。这感觉很重 - 是否有其他系统实现这一点的更简单方法(例如,SharePoint 有很多用户数据库引用的插件)?我的应用程序在编译时规定了它支持的接口并忽略了所有其他接口 - 我已经看到一些系统声称可以使用开放插件完全扩展,我认为这意味着许多松散类型的接口和强制转换,是否存在中间立场这两个选项允许在不重新编译的情况下发布未来更新但仍使用具体接口?
我的插件可能包含元数据(PluginProperty 或 PluginSetting),我不确定存储它的最佳位置,无论是在插件元数据表中(会使 linq 查询更复杂)还是直接在插件数据库记录行中(简单的 linq 查询
PluginManager.GetPluginsOfType<IAccounts>.Where(x => x.ShortCode = "externaldata").FirstOrDefault();
,即用作最佳实践?由于插件功能和接口严重依赖于数据库模式,我可以限制插件与特定模式修订版一起使用的推荐方法是什么?我是否会将此架构修订作为单行保留在数据库的设置表中,并在每次发布后手动更新?插件是否支持最大架构版本,或者应用程序是否支持已知插件版本列表?