增强插件系统:添加操作参数信息获取功能
- 在插件接口中新增 GetOperationInfo 和 GetAllOperations 方法,支持获取特定操作及所有操作的参数信息。 - 更新 PluginHelper 以实现获取操作参数信息的功能,提升插件的可用性和灵活性。 - 在日志插件中实现操作信息获取,展示如何使用新方法获取操作的详细参数信息。 - 示例程序中添加新的选项,展示如何获取插件操作的参数信息。 此更新提升了插件系统的可扩展性和易用性,便于开发者更好地管理和使用插件功能。
This commit is contained in:
@@ -43,6 +43,10 @@ type Plugin interface {
|
||||
// params: 操作所需的参数
|
||||
// 返回操作结果和可能的错误
|
||||
Execute(ctx context.Context, action string, params map[string]interface{}) (interface{}, error)
|
||||
// GetOperationInfo 获取操作的参数信息
|
||||
GetOperationInfo(operation string) (map[string]interface{}, error)
|
||||
// GetAllOperations 获取所有操作及其参数信息
|
||||
GetAllOperations() map[string]map[string]interface{}
|
||||
}
|
||||
|
||||
// PluginHelper 插件辅助器
|
||||
@@ -469,6 +473,169 @@ func convertParamValue(value interface{}, targetType reflect.Type) (reflect.Valu
|
||||
return reflect.Value{}, fmt.Errorf("不支持将 %T 类型转换为 %s", value, targetType)
|
||||
}
|
||||
|
||||
// GetParameterInfo 获取操作的参数信息
|
||||
func (h *PluginHelper) GetParameterInfo(action string) (map[string]interface{}, error) {
|
||||
action = strings.ToLower(action)
|
||||
method, exists := h.methods[action]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("未知的操作: %s", action)
|
||||
}
|
||||
|
||||
paramTypes := h.methodParams[action]
|
||||
returnTypes := h.methodRetValues[action]
|
||||
|
||||
result := map[string]interface{}{
|
||||
"name": action,
|
||||
"description": fmt.Sprintf("%s 操作", method.Name),
|
||||
"parameters": make(map[string]interface{}),
|
||||
"returns": make(map[string]interface{}),
|
||||
}
|
||||
|
||||
// 处理参数信息
|
||||
paramsInfo := make(map[string]interface{})
|
||||
|
||||
// 首先检查是否有context参数
|
||||
hasContext := false
|
||||
if len(paramTypes) > 0 && paramTypes[0].String() == "context.Context" {
|
||||
hasContext = true
|
||||
result["hasContext"] = true
|
||||
paramTypes = paramTypes[1:] // 跳过context参数
|
||||
}
|
||||
|
||||
for i, paramType := range paramTypes {
|
||||
// 如果是结构体参数,展开其字段
|
||||
if paramType.Kind() == reflect.Struct {
|
||||
structInfo := getStructInfo(paramType)
|
||||
structInfo["position"] = i + 1 // 考虑到接收者和可能的context
|
||||
if hasContext {
|
||||
structInfo["position"] = i + 2
|
||||
}
|
||||
paramsInfo[paramType.Name()] = structInfo
|
||||
} else {
|
||||
// 基本类型参数
|
||||
paramName := fmt.Sprintf("arg%d", i)
|
||||
typeInfo := getTypeInfo(paramType)
|
||||
typeInfo["position"] = i + 1 // 考虑到接收者
|
||||
if hasContext {
|
||||
typeInfo["position"] = i + 2
|
||||
}
|
||||
paramsInfo[paramName] = typeInfo
|
||||
}
|
||||
}
|
||||
result["parameters"] = paramsInfo
|
||||
|
||||
// 处理返回值信息
|
||||
returnsInfo := make(map[string]interface{})
|
||||
for i, returnType := range returnTypes {
|
||||
returnName := fmt.Sprintf("return%d", i)
|
||||
if i == len(returnTypes)-1 && returnType.String() == "error" {
|
||||
returnName = "error"
|
||||
} else if i == 0 && len(returnTypes) == 2 && returnTypes[1].String() == "error" {
|
||||
returnName = "result"
|
||||
}
|
||||
returnsInfo[returnName] = getTypeInfo(returnType)
|
||||
}
|
||||
result["returns"] = returnsInfo
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// getStructInfo 获取结构体类型的详细信息
|
||||
func getStructInfo(t reflect.Type) map[string]interface{} {
|
||||
info := map[string]interface{}{
|
||||
"type": "struct",
|
||||
"name": t.Name(),
|
||||
"package": t.PkgPath(),
|
||||
"fields": make(map[string]interface{}),
|
||||
"fieldCount": t.NumField(),
|
||||
}
|
||||
|
||||
fields := make(map[string]interface{})
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
|
||||
// 跳过非导出字段
|
||||
if field.PkgPath != "" {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldName := field.Name
|
||||
jsonTag := field.Tag.Get("json")
|
||||
if jsonTag != "" && jsonTag != "-" {
|
||||
parts := strings.Split(jsonTag, ",")
|
||||
if parts[0] != "" {
|
||||
fieldName = parts[0]
|
||||
}
|
||||
}
|
||||
|
||||
fieldInfo := getTypeInfo(field.Type)
|
||||
fieldInfo["name"] = field.Name
|
||||
fieldInfo["jsonName"] = fieldName
|
||||
fieldInfo["position"] = i
|
||||
fieldInfo["tags"] = string(field.Tag)
|
||||
|
||||
fields[fieldName] = fieldInfo
|
||||
}
|
||||
info["fields"] = fields
|
||||
|
||||
return info
|
||||
}
|
||||
|
||||
// getTypeInfo 获取类型的基本信息
|
||||
func getTypeInfo(t reflect.Type) map[string]interface{} {
|
||||
info := map[string]interface{}{
|
||||
"typeName": t.String(),
|
||||
"kind": t.Kind().String(),
|
||||
"type": typeKindToString(t.Kind()),
|
||||
}
|
||||
|
||||
// 为不同类型添加特定信息
|
||||
switch t.Kind() {
|
||||
case reflect.Slice, reflect.Array:
|
||||
info["elemType"] = getTypeInfo(t.Elem())
|
||||
case reflect.Map:
|
||||
info["keyType"] = getTypeInfo(t.Key())
|
||||
info["valueType"] = getTypeInfo(t.Elem())
|
||||
case reflect.Ptr:
|
||||
info["elemType"] = getTypeInfo(t.Elem())
|
||||
case reflect.Struct:
|
||||
// 对于结构体,提供简略信息
|
||||
info["structName"] = t.Name()
|
||||
info["package"] = t.PkgPath()
|
||||
info["fieldCount"] = t.NumField()
|
||||
}
|
||||
|
||||
return info
|
||||
}
|
||||
|
||||
// typeKindToString 将类型Kind转换为字符串表示
|
||||
func typeKindToString(kind reflect.Kind) string {
|
||||
switch kind {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return "integer"
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return "unsigned integer"
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return "float"
|
||||
case reflect.Bool:
|
||||
return "boolean"
|
||||
case reflect.String:
|
||||
return "string"
|
||||
case reflect.Slice, reflect.Array:
|
||||
return "array"
|
||||
case reflect.Map:
|
||||
return "map"
|
||||
case reflect.Struct:
|
||||
return "object"
|
||||
case reflect.Ptr:
|
||||
return "pointer"
|
||||
case reflect.Interface:
|
||||
return "interface"
|
||||
default:
|
||||
return kind.String()
|
||||
}
|
||||
}
|
||||
|
||||
// BasePluginImpl 提供插件接口的基本实现,用于适配Plugin接口
|
||||
// 这个结构体包装了BasePlugin,以便兼容context参数
|
||||
type BasePluginImpl struct {
|
||||
@@ -531,6 +698,23 @@ func (p *BasePluginImpl) GetAvailableActions() []string {
|
||||
return p.helper.GetAvailableActions()
|
||||
}
|
||||
|
||||
// GetOperationInfo 获取操作的参数信息
|
||||
func (p *BasePluginImpl) GetOperationInfo(operation string) (map[string]interface{}, error) {
|
||||
return p.helper.GetParameterInfo(operation)
|
||||
}
|
||||
|
||||
// GetAllOperations 获取所有操作及其参数信息
|
||||
func (p *BasePluginImpl) GetAllOperations() map[string]map[string]interface{} {
|
||||
operations := make(map[string]map[string]interface{})
|
||||
for _, action := range p.helper.GetAvailableActions() {
|
||||
info, err := p.helper.GetParameterInfo(action)
|
||||
if err == nil {
|
||||
operations[action] = info
|
||||
}
|
||||
}
|
||||
return operations
|
||||
}
|
||||
|
||||
// PluginInfo 插件信息
|
||||
type PluginInfo struct {
|
||||
Name string `json:"name"`
|
||||
@@ -1099,3 +1283,75 @@ func (pm *PluginManager) ExecuteAllPlugins(ctx context.Context, action string, p
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
// GetPluginOperationInfo 获取插件特定操作的参数信息
|
||||
func (pm *PluginManager) GetPluginOperationInfo(name string, operation string) (map[string]interface{}, error) {
|
||||
pm.mu.RLock()
|
||||
defer pm.mu.RUnlock()
|
||||
|
||||
plugin, exists := pm.plugins[name]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("插件 %s 不存在", name)
|
||||
}
|
||||
|
||||
if !plugin.IsEnabled() {
|
||||
return nil, fmt.Errorf("插件 %s 已禁用", name)
|
||||
}
|
||||
|
||||
return plugin.GetOperationInfo(operation)
|
||||
}
|
||||
|
||||
// GetPluginAllOperations 获取插件所有操作及其参数信息
|
||||
func (pm *PluginManager) GetPluginAllOperations(name string) (map[string]map[string]interface{}, error) {
|
||||
pm.mu.RLock()
|
||||
defer pm.mu.RUnlock()
|
||||
|
||||
plugin, exists := pm.plugins[name]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("插件 %s 不存在", name)
|
||||
}
|
||||
|
||||
if !plugin.IsEnabled() {
|
||||
return nil, fmt.Errorf("插件 %s 已禁用", name)
|
||||
}
|
||||
|
||||
return plugin.GetAllOperations(), nil
|
||||
}
|
||||
|
||||
// GetOperationsByType 获取指定类型插件的所有操作信息
|
||||
func (pm *PluginManager) GetOperationsByType(pluginType PluginType) map[string]map[string]map[string]interface{} {
|
||||
pm.mu.RLock()
|
||||
defer pm.mu.RUnlock()
|
||||
|
||||
result := make(map[string]map[string]map[string]interface{})
|
||||
|
||||
if typePlugins, exists := pm.pluginsByType[pluginType]; exists {
|
||||
for name, plugin := range typePlugins {
|
||||
if !plugin.IsEnabled() {
|
||||
continue
|
||||
}
|
||||
|
||||
result[name] = plugin.GetAllOperations()
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// GetAllPluginsOperations 获取所有插件的所有操作信息
|
||||
func (pm *PluginManager) GetAllPluginsOperations() map[string]map[string]map[string]interface{} {
|
||||
pm.mu.RLock()
|
||||
defer pm.mu.RUnlock()
|
||||
|
||||
result := make(map[string]map[string]map[string]interface{})
|
||||
|
||||
for name, plugin := range pm.plugins {
|
||||
if !plugin.IsEnabled() {
|
||||
continue
|
||||
}
|
||||
|
||||
result[name] = plugin.GetAllOperations()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
Reference in New Issue
Block a user