API/插件架构开发理念

本文关键字:开发 插件架 API | 更新日期: 2023-09-27 18:01:13

我正试图找到一种开发基于插件的体系结构软件的方法。基本结构是,我的主应用程序("MainApp"(将启动,搜索指定文件夹中的插件DLL文件,并使用Activator逐个加载它们。DLL文件应该是由我的团队创建的,我计划为其他用户提供一个文档来开发插件。

现在我有一个正在运行的示例项目。我使用了一个接口类("插件接口"(,通过它可以转换类型并加载插件。我可以通过指定的函数、属性和子例程与插件进行通信。

我的问题是接口方法定义了在插件类中可以找到哪些属性、函数、子类或事件。我想做的是,我的MainApp中有许多可用的组件或控件。我需要允许我的插件访问这些组件。例如,我有一个通知控件('NotifyCtrl'(,它允许插件在屏幕上显示弹出通知。该控件有自己的属性和方法。所以我有一个很大的控制武器库,我想允许插件访问。

我无法理解如何开发这样的架构,即运行时加载的插件能够访问MainApp的控件/组件。我的意思是,我可以使用PluginInterface访问插件的组件,但插件如何知道MainApp可以使用哪些组件/属性/功能。我应该如何在我的插件中编写代码(例如"ChatPlugin"(…。MainApp.NotifyCtrl.ShowNotification("你好"(?

感谢

API/插件架构开发理念

在这种情况下,您需要做的是创建一个基本库,您的应用程序从该库中运行。这意味着您需要为插件开发人员看到的每个类创建一个抽象类或接口。

例如,在你的主应用程序中,假设你有一个"用户"类,你想让它共享事件和变量:

    //Create an instance of user in your application where you allow setting and getting the Name.
    public class User : IUser
    {
        public string Name { get; set; }
        public string Id { get; set; }
        public event Action OnLogin = delegate { };
    }

    //Only allow the developers to get the name/id
    public interface IUser
    {
        string Name { get; }
        string Id { get; }
        event Action OnLogin;
    }

然后,例如,如果您希望开发人员访问应用程序中的所有登录用户,那么您就有了某种主要的连接点,例如一个静态类,您可以在其中管理所有内容。

    //Your functionality goes here
    public class UserManager : IUserManager
    {
        private Dictionary<int, User> Users = new Dictionary<int, User>();
        public override User this[int id]
        {
            get { return Users[id];}
        }
        public override IEnumerator<IUser> GetEnumerator()
        {
            return Users.Values.GetEnumerator();
        }
        public void Add(User user)
        {
            Users[user.Id] = user;
        }
    }
    //What the user can see goes here
    public abstract class IUserManager : IEnumerable<IUser>
    {
        public abstract User this[int id] { get; }
        public abstract IEnumerator<IUser> GetEnumerator();
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }

将其全部捆绑起来,并允许他们完全访问枚举:

public class MyApp : MyPluginApp
    {
        public static UserManager MyUserManager { get { return Manager as UserManager; } }
        public static void Start()
        {
            //Start routine
            Manager = new UserManager();

            MyUserManager.Add(new User {Id = 0, Name = "test"});
        }
    }
    public class MyPluginApp
    {
        public static IUserManager Manager { get; protected set; }
    }

然后,你的插件开发人员可以做一些简单的事情:

var userOfInterest = MyPluginApp.Manager.First(x => x.Name == "test"); //Get user by the name of test

他们可以很容易地访问Id/name,但他们不能设置它,也不能添加新用户等。这也让你更容易,因为你不需要为每个想要导出的函数创建额外的函数,相反,你只需要在基类中创建一个函数,并在应用程序中实现它。

我想我已经找到了我想要的解决方案。使用反射方法加载插件是运行时通常是单向交互的方法。。。主机应用程序使用插件类的功能。我正在寻找的是两种方式,主机使用插件的资源和插件使用主机的控制/资源等。

因此"反射"方法已经过时。3.5及以上的.NET框架提供了System.AddIn功能,这是为此类架构而设计的。

请参阅http://msdn.microsoft.com/en-us/magazine/cc163476.aspx