C#插件架构和对用户可配置数据库设置的引用

前端之家收集整理的这篇文章主要介绍了C#插件架构和对用户可配置数据库设置的引用前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个可由用户配置的数据库应用程序 – 其中一些选项是从不同的外部插件系统中进行选择.

我有一个基本的插件类型,我的数据库模式具有相同的插件记录类型与相同的字段.我有一个PlugingMananger在应用程序启动时加载插件(通过IoC容器),并将它们链接数据库(基本上将磁盘上的插件的字段复制到数据库).

public interface IPlugin
{
    Guid Id{ get; }
    Version Version { get; }
    string Name { get; }
    string Description { get; }
}

然后可以使用PlugingMananger.GetPlugin(Guid pluginId,Guid userId)检索插件,其中用户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); }
    }

    public string PluginName
    {
        get { return "Data connector"; }
    }

    public string PluginDescription
    {
        get { return "Connector for collecting data"; }
    }
}

以下是我正在寻求指导的问题和领域:

>通过以上抽象将IoC容器中的插件链接数据库,用户可以选择数据库字段Customer.ExternalAccountsPlugin = idOfExternalPlugin.这感觉很沉重 – 其他系统是否实现了更简单的方式(例如SharePoint具有大量用户数据库引用的插件)?
>我的应用程序在编译时指定它支持的接口并忽略所有其他接口 – 我已经看到一些系统声称可以使用开放式插件完全展开,我认为这意味着许多松散类型的接口和投射,是否有一个中间路在两个选项之间,这将允许未来的更新发布,而不重新编译,但仍然使用具体的接口?
>我的插件可以包含元数据(PluginProperty或PluginSetting),我不确定存储这个的最佳位置,在插件元数据表(将使linq查询更复杂)或直接插入数据库记录行(easy linq查询PluginManager. GetPluginsOfType< IAccounts> .Where(x => x.ShortCode =“externaldata”).FirstOrDefault();作为最佳实践使用?
>由于插件功能和接口在数据库架构上非常依赖,所以推荐的方法是限制一个插件与特定架构修订版本的配合使用?我将数据库中的设置表中的单个行保留在该模式修订版中,并在每次发布后手动更新?插件是否支持最大模式版本,还是应用程序支持已知插件版本的列表?

解决方法

1)对不起,我不知道.不过,我非常确定,在通过自定义插件创建或处理数据的软件中,他们按照您所描述的方式处理插件.这个想法是,如果用户加载数据但缺少该特定插件,则数据不会被损坏,并且不允许用户修改该数据. (我想到的一个例子是3D软件)

2)只有给出非常严格的界面实现,当然高度限制了插件的创建. (例如:Excel,我不能创建一个新的单元格类型)它不坏还是不错,它高度依赖于你想要的,这是一个选择.如果您希望插件创建者仅通过一些特定的管道访问数据,则可以限制他可以创建的数据类型,然后与您的设计一起使用.否则,如果您的目标是开发您的软件来改进,那么您还应该公开一些您认为足够安全的类和方法,以便在外部使用. (例如:Maya,我可以创建一个从基类派生的新实体类型,而不仅仅是一个接口)

3)嗯,这确实取决于很多事情,不是吗?序列化数据时,您可以创建一个包含特定插件,ID,MetaData以及其他任何您需要判断的信息的包装器.我会去那样,因为它会更容易检索,但它是你需要什么的最佳方法?很难说没有更多的信息.

4)一个很好的例子就是Firefox.较小的版本增量不会改变插件兼容性.如果插件仍然有效,则从数据库进行中等版本的增量测试,以考虑其实现的内容.如果插件没有实现改变的东西,它仍然有效.主要版本增量需要重新编译所有插件才能使用新的定义.从我的角度来看,这是一个很好的中间原因,允许开发人员不会总是重新编译,但是由于变更必须在未来计划中,因此主要软件的开发会更加棘手.这个想法是平衡软件开发人员和插件开发人员之间的PitA(Pain in the Ass)因素.

那么这是我的2美分的收集.

猜你在找的C#相关文章