增强插件系统:优化插件管理和动态插件实现
- 在插件管理器中引入 DynamicPlugin 结构体,支持动态加载和管理插件,提升插件的灵活性和可扩展性。 - 更新插件接口,添加插件名称、版本、描述、作者、类型和启用状态的获取和设置方法,增强插件信息的管理能力。 - 修改现有插件实现,确保兼容新的动态插件结构,提升插件的统一性和可维护性。 - 更新示例程序,展示如何使用新的动态插件功能,提升用户体验。 此更新提升了插件系统的灵活性和可扩展性,便于开发者更好地管理和使用插件功能。
This commit is contained in:
@@ -3,7 +3,6 @@ package plugin
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
@@ -978,36 +977,445 @@ func (pm *PluginManager) loadPlugin(path string) error {
|
||||
return fmt.Errorf("查找Plugin变量失败: %v", err)
|
||||
}
|
||||
|
||||
// 类型断言
|
||||
plugin, ok := symPlugin.(Plugin)
|
||||
if !ok {
|
||||
return errors.New("插件类型错误")
|
||||
// 使用反射检查插件对象
|
||||
pluginValue := reflect.ValueOf(symPlugin)
|
||||
fmt.Printf("加载插件: %s, 类型: %s\n", path, pluginValue.Type())
|
||||
|
||||
// 查找基本字段或方法
|
||||
var pluginName, pluginVersion, pluginAuthor, pluginDesc string
|
||||
var pluginType PluginType = PluginTypeGeneral
|
||||
var enabled = true
|
||||
|
||||
// 直接检查方法
|
||||
// 尝试通过方法获取信息
|
||||
nameFound := false
|
||||
if nameMethod := pluginValue.MethodByName("Name"); nameMethod.IsValid() {
|
||||
results := nameMethod.Call(nil)
|
||||
if len(results) > 0 && results[0].Kind() == reflect.String {
|
||||
pluginName = results[0].String()
|
||||
nameFound = true
|
||||
}
|
||||
}
|
||||
|
||||
if versionMethod := pluginValue.MethodByName("Version"); versionMethod.IsValid() {
|
||||
results := versionMethod.Call(nil)
|
||||
if len(results) > 0 && results[0].Kind() == reflect.String {
|
||||
pluginVersion = results[0].String()
|
||||
}
|
||||
}
|
||||
|
||||
if descMethod := pluginValue.MethodByName("Description"); descMethod.IsValid() {
|
||||
results := descMethod.Call(nil)
|
||||
if len(results) > 0 && results[0].Kind() == reflect.String {
|
||||
pluginDesc = results[0].String()
|
||||
}
|
||||
}
|
||||
|
||||
if authorMethod := pluginValue.MethodByName("Author"); authorMethod.IsValid() {
|
||||
results := authorMethod.Call(nil)
|
||||
if len(results) > 0 && results[0].Kind() == reflect.String {
|
||||
pluginAuthor = results[0].String()
|
||||
}
|
||||
}
|
||||
|
||||
if typeMethod := pluginValue.MethodByName("Type"); typeMethod.IsValid() {
|
||||
results := typeMethod.Call(nil)
|
||||
if len(results) > 0 {
|
||||
// 尝试匹配插件类型
|
||||
typeStr := fmt.Sprint(results[0].Interface())
|
||||
switch typeStr {
|
||||
case "storage":
|
||||
pluginType = PluginTypeStorage
|
||||
case "security":
|
||||
pluginType = PluginTypeSecurity
|
||||
case "network":
|
||||
pluginType = PluginTypeNetwork
|
||||
case "utils":
|
||||
pluginType = PluginTypeUtils
|
||||
case "hardware":
|
||||
pluginType = PluginTypeHardware
|
||||
case "ui":
|
||||
pluginType = PluginTypeUI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 直接检查字段(仅在方法不可用时)
|
||||
if !nameFound && pluginValue.Kind() == reflect.Ptr && !pluginValue.IsNil() {
|
||||
elemValue := pluginValue.Elem()
|
||||
|
||||
// 检查elemValue是否为结构体
|
||||
if elemValue.Kind() == reflect.Struct {
|
||||
// 检查是否有name字段
|
||||
if nameField := elemValue.FieldByName("name"); nameField.IsValid() && nameField.Kind() == reflect.String {
|
||||
pluginName = nameField.String()
|
||||
}
|
||||
|
||||
// 检查是否有version字段
|
||||
if versionField := elemValue.FieldByName("version"); versionField.IsValid() && versionField.Kind() == reflect.String {
|
||||
pluginVersion = versionField.String()
|
||||
}
|
||||
|
||||
// 检查是否有description字段
|
||||
if descField := elemValue.FieldByName("description"); descField.IsValid() && descField.Kind() == reflect.String {
|
||||
pluginDesc = descField.String()
|
||||
}
|
||||
|
||||
// 检查是否有author字段
|
||||
if authorField := elemValue.FieldByName("author"); authorField.IsValid() && authorField.Kind() == reflect.String {
|
||||
pluginAuthor = authorField.String()
|
||||
}
|
||||
|
||||
// 检查是否有pluginType字段
|
||||
if typeField := elemValue.FieldByName("pluginType"); typeField.IsValid() {
|
||||
// 转换为字符串并尝试匹配已知类型
|
||||
typeStr := fmt.Sprint(typeField.Interface())
|
||||
switch typeStr {
|
||||
case "storage":
|
||||
pluginType = PluginTypeStorage
|
||||
case "security":
|
||||
pluginType = PluginTypeSecurity
|
||||
case "network":
|
||||
pluginType = PluginTypeNetwork
|
||||
case "utils":
|
||||
pluginType = PluginTypeUtils
|
||||
case "hardware":
|
||||
pluginType = PluginTypeHardware
|
||||
case "ui":
|
||||
pluginType = PluginTypeUI
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否有enabled字段
|
||||
if enabledField := elemValue.FieldByName("enabled"); enabledField.IsValid() && enabledField.Kind() == reflect.Bool {
|
||||
enabled = enabledField.Bool()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果名称仍为空,则使用文件名
|
||||
if pluginName == "" {
|
||||
// 从路径中提取文件名并去掉扩展名
|
||||
fileName := filepath.Base(path)
|
||||
pluginName = strings.TrimSuffix(fileName, filepath.Ext(fileName))
|
||||
}
|
||||
|
||||
fmt.Printf("创建适配器插件: 名称=%s, 版本=%s, 作者=%s, 类型=%s\n",
|
||||
pluginName, pluginVersion, pluginAuthor, pluginType)
|
||||
|
||||
// 创建一个自定义插件结构体
|
||||
customPlugin := &DynamicPlugin{
|
||||
original: symPlugin,
|
||||
name: pluginName,
|
||||
version: pluginVersion,
|
||||
description: pluginDesc,
|
||||
author: pluginAuthor,
|
||||
pluginType: pluginType,
|
||||
enabled: enabled,
|
||||
}
|
||||
|
||||
// 检查插件名称是否已存在
|
||||
pm.mu.Lock()
|
||||
defer pm.mu.Unlock()
|
||||
|
||||
if _, exists := pm.plugins[plugin.Name()]; exists {
|
||||
return fmt.Errorf("插件 %s 已存在", plugin.Name())
|
||||
if _, exists := pm.plugins[customPlugin.Name()]; exists {
|
||||
return fmt.Errorf("插件 %s 已存在", customPlugin.Name())
|
||||
}
|
||||
|
||||
// 设置插件启用状态
|
||||
if config, exists := pm.configs[plugin.Name()]; exists {
|
||||
if config, exists := pm.configs[customPlugin.Name()]; exists {
|
||||
if enabled, ok := config["enabled"].(bool); ok {
|
||||
plugin.SetEnabled(enabled)
|
||||
} else {
|
||||
plugin.SetEnabled(true) // 默认启用
|
||||
customPlugin.enabled = enabled
|
||||
}
|
||||
} else {
|
||||
plugin.SetEnabled(true) // 默认启用
|
||||
}
|
||||
|
||||
// 注册插件
|
||||
pm.registerPlugin(plugin)
|
||||
pm.registerPlugin(customPlugin)
|
||||
fmt.Printf("已成功注册插件: %s\n", customPlugin.Name())
|
||||
return nil
|
||||
}
|
||||
|
||||
// DynamicPlugin 完全动态的插件实现
|
||||
type DynamicPlugin struct {
|
||||
original interface{}
|
||||
name string
|
||||
version string
|
||||
description string
|
||||
author string
|
||||
pluginType PluginType
|
||||
enabled bool
|
||||
}
|
||||
|
||||
// Name 返回插件名称
|
||||
func (p *DynamicPlugin) Name() string {
|
||||
return p.name
|
||||
}
|
||||
|
||||
// Version 返回插件版本
|
||||
func (p *DynamicPlugin) Version() string {
|
||||
return p.version
|
||||
}
|
||||
|
||||
// Description 返回插件描述
|
||||
func (p *DynamicPlugin) Description() string {
|
||||
return p.description
|
||||
}
|
||||
|
||||
// Author 返回插件作者
|
||||
func (p *DynamicPlugin) Author() string {
|
||||
return p.author
|
||||
}
|
||||
|
||||
// Type 返回插件类型
|
||||
func (p *DynamicPlugin) Type() PluginType {
|
||||
return p.pluginType
|
||||
}
|
||||
|
||||
// IsEnabled 返回插件是否启用
|
||||
func (p *DynamicPlugin) IsEnabled() bool {
|
||||
return p.enabled
|
||||
}
|
||||
|
||||
// SetEnabled 设置插件启用状态
|
||||
func (p *DynamicPlugin) SetEnabled(enabled bool) {
|
||||
p.enabled = enabled
|
||||
|
||||
// 尝试调用原始插件的SetEnabled方法
|
||||
method := reflect.ValueOf(p.original).MethodByName("SetEnabled")
|
||||
if method.IsValid() {
|
||||
method.Call([]reflect.Value{reflect.ValueOf(enabled)})
|
||||
}
|
||||
}
|
||||
|
||||
// Init 初始化插件
|
||||
func (p *DynamicPlugin) Init(ctx context.Context, config map[string]interface{}) error {
|
||||
method := reflect.ValueOf(p.original).MethodByName("Init")
|
||||
if !method.IsValid() {
|
||||
return nil // 如果方法不存在,就不做任何事情
|
||||
}
|
||||
|
||||
// 确定方法参数数量和类型
|
||||
methodType := method.Type()
|
||||
numParams := methodType.NumIn()
|
||||
|
||||
// 准备参数
|
||||
var args []reflect.Value
|
||||
|
||||
// 对于不同参数数量的处理
|
||||
switch numParams {
|
||||
case 0:
|
||||
// 无参数
|
||||
case 1:
|
||||
// 只有一个参数,可能是配置
|
||||
args = append(args, reflect.ValueOf(config))
|
||||
case 2:
|
||||
// 两个参数,可能是上下文和配置
|
||||
args = append(args, reflect.ValueOf(ctx), reflect.ValueOf(config))
|
||||
default:
|
||||
// 不支持更多参数
|
||||
return fmt.Errorf("不支持的Init方法参数数量: %d", numParams)
|
||||
}
|
||||
|
||||
// 调用方法
|
||||
results := method.Call(args)
|
||||
|
||||
// 处理返回值
|
||||
if len(results) > 0 && results[0].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
||||
if !results[0].IsNil() {
|
||||
return results[0].Interface().(error)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Start 启动插件
|
||||
func (p *DynamicPlugin) Start(ctx context.Context) error {
|
||||
method := reflect.ValueOf(p.original).MethodByName("Start")
|
||||
if !method.IsValid() {
|
||||
return nil // 如果方法不存在,就不做任何事情
|
||||
}
|
||||
|
||||
// 确定方法参数数量和类型
|
||||
methodType := method.Type()
|
||||
numParams := methodType.NumIn()
|
||||
|
||||
// 准备参数
|
||||
var args []reflect.Value
|
||||
|
||||
// 对于不同参数数量的处理
|
||||
switch numParams {
|
||||
case 0:
|
||||
// 无参数
|
||||
case 1:
|
||||
// 一个参数,可能是上下文
|
||||
args = append(args, reflect.ValueOf(ctx))
|
||||
default:
|
||||
// 不支持更多参数
|
||||
return fmt.Errorf("不支持的Start方法参数数量: %d", numParams)
|
||||
}
|
||||
|
||||
// 调用方法
|
||||
results := method.Call(args)
|
||||
|
||||
// 处理返回值
|
||||
if len(results) > 0 && results[0].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
||||
if !results[0].IsNil() {
|
||||
return results[0].Interface().(error)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop 停止插件
|
||||
func (p *DynamicPlugin) Stop(ctx context.Context) error {
|
||||
method := reflect.ValueOf(p.original).MethodByName("Stop")
|
||||
if !method.IsValid() {
|
||||
return nil // 如果方法不存在,就不做任何事情
|
||||
}
|
||||
|
||||
// 确定方法参数数量和类型
|
||||
methodType := method.Type()
|
||||
numParams := methodType.NumIn()
|
||||
|
||||
// 准备参数
|
||||
var args []reflect.Value
|
||||
|
||||
// 对于不同参数数量的处理
|
||||
switch numParams {
|
||||
case 0:
|
||||
// 无参数
|
||||
case 1:
|
||||
// 一个参数,可能是上下文
|
||||
args = append(args, reflect.ValueOf(ctx))
|
||||
default:
|
||||
// 不支持更多参数
|
||||
return fmt.Errorf("不支持的Stop方法参数数量: %d", numParams)
|
||||
}
|
||||
|
||||
// 调用方法
|
||||
results := method.Call(args)
|
||||
|
||||
// 处理返回值
|
||||
if len(results) > 0 && results[0].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
||||
if !results[0].IsNil() {
|
||||
return results[0].Interface().(error)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Execute 执行插件功能
|
||||
func (p *DynamicPlugin) Execute(ctx context.Context, action string, params map[string]interface{}) (interface{}, error) {
|
||||
method := reflect.ValueOf(p.original).MethodByName("Execute")
|
||||
if !method.IsValid() {
|
||||
return nil, fmt.Errorf("插件不支持Execute方法")
|
||||
}
|
||||
|
||||
// 确定方法参数数量和类型
|
||||
methodType := method.Type()
|
||||
numParams := methodType.NumIn()
|
||||
|
||||
// 准备参数
|
||||
var args []reflect.Value
|
||||
|
||||
// 对于不同参数数量的处理
|
||||
switch numParams {
|
||||
case 2:
|
||||
// 两个参数,可能是action和params
|
||||
args = append(args, reflect.ValueOf(action), reflect.ValueOf(params))
|
||||
case 3:
|
||||
// 三个参数,可能是ctx、action和params
|
||||
args = append(args, reflect.ValueOf(ctx), reflect.ValueOf(action), reflect.ValueOf(params))
|
||||
default:
|
||||
// 不支持其他参数数量
|
||||
return nil, fmt.Errorf("不支持的Execute方法参数数量: %d", numParams)
|
||||
}
|
||||
|
||||
// 调用方法
|
||||
results := method.Call(args)
|
||||
|
||||
// 处理返回值
|
||||
var result interface{}
|
||||
var err error
|
||||
|
||||
switch len(results) {
|
||||
case 1:
|
||||
// 只有一个返回值,检查是否为错误
|
||||
if results[0].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
||||
if !results[0].IsNil() {
|
||||
err = results[0].Interface().(error)
|
||||
}
|
||||
} else {
|
||||
result = results[0].Interface()
|
||||
}
|
||||
case 2:
|
||||
// 两个返回值,第一个是结果,第二个是错误
|
||||
if !results[0].IsNil() {
|
||||
result = results[0].Interface()
|
||||
}
|
||||
|
||||
if results[1].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
||||
if !results[1].IsNil() {
|
||||
err = results[1].Interface().(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
// GetOperationInfo 获取操作的参数信息
|
||||
func (p *DynamicPlugin) GetOperationInfo(operation string) (map[string]interface{}, error) {
|
||||
method := reflect.ValueOf(p.original).MethodByName("GetOperationInfo")
|
||||
if !method.IsValid() {
|
||||
return map[string]interface{}{}, nil
|
||||
}
|
||||
|
||||
results := method.Call([]reflect.Value{reflect.ValueOf(operation)})
|
||||
|
||||
var result map[string]interface{}
|
||||
var err error
|
||||
|
||||
if len(results) > 0 && !results[0].IsNil() {
|
||||
if m, ok := results[0].Interface().(map[string]interface{}); ok {
|
||||
result = m
|
||||
} else {
|
||||
result = map[string]interface{}{}
|
||||
}
|
||||
} else {
|
||||
result = map[string]interface{}{}
|
||||
}
|
||||
|
||||
if len(results) > 1 && results[1].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
||||
if !results[1].IsNil() {
|
||||
err = results[1].Interface().(error)
|
||||
}
|
||||
}
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
// GetAllOperations 获取所有操作及其参数信息
|
||||
func (p *DynamicPlugin) GetAllOperations() map[string]map[string]interface{} {
|
||||
method := reflect.ValueOf(p.original).MethodByName("GetAllOperations")
|
||||
if !method.IsValid() {
|
||||
return map[string]map[string]interface{}{}
|
||||
}
|
||||
|
||||
results := method.Call(nil)
|
||||
|
||||
if len(results) > 0 && !results[0].IsNil() {
|
||||
if m, ok := results[0].Interface().(map[string]map[string]interface{}); ok {
|
||||
return m
|
||||
}
|
||||
}
|
||||
|
||||
return map[string]map[string]interface{}{}
|
||||
}
|
||||
|
||||
// registerPlugin 注册插件到插件管理器
|
||||
func (pm *PluginManager) registerPlugin(plugin Plugin) {
|
||||
pluginType := plugin.Type()
|
||||
@@ -1460,4 +1868,4 @@ func (pm *PluginManager) GetAllPluginsOperations() map[string]map[string]map[str
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user