【问题标题】:how to pass object parameters in command?如何在命令中传递对象参数?
【发布时间】:2014-01-14 19:27:43
【问题描述】:

我用一个带参数的新命令创建了一个 eclipse-rcp 项目的 plugin.xml。

 ArrayList<parameterization> parameters = new ArrayList<parameterization>();
 IParameter iparam;

 //get the command from plugin.xml
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
 ICommandService cmdService =     (ICommandService)window.getService(ICommandService.class);
 Command cmd = cmdService.getCommand("org.ipiel.demo.commands.click");

//get the parameter
iparam = cmd.getParameter("org.ipiel.demo.commands.click.paramenter1");
Parameterization params = new Parameterization(iparam, "commandValue");
parameters.add(params);

//build the parameterized command
 ParameterizedCommand pc = new ParameterizedCommand(cmd, parameters.toArray(new       Parameterization[parameters.size()]));

//execute the command
 IHandlerService handlerService = (IHandlerService)window.getService(IHandlerService.class);
handlerService.executeCommand(pc, null);

我尝试了这个例子来传递参数,它成功了。

这个例子中的问题是我只能传递字符串类型的参数。 (因为参数化)

我想传递哈希映射的参数,一般来说传递任何对象。

我试过这段代码

     IServiceLocator serviceLocator = PlatformUI.getWorkbench();
    ICommandService commandService = (ICommandService)      serviceLocator.getService(ICommandService.class);




    ExecutionEvent executionEvent = new ExecutionEvent(cmd, paramArray, null, null);
    cmd.executeWithChecks(executionEvent);

但它没有工作参数没有移动(它是空的)

您能帮忙在命令中将对象作为参数移动吗?

【问题讨论】:

    标签: java eclipse-plugin


    【解决方案1】:

    由于在我的第一个答案中添加另一个解决方案会让人感到困惑,我将为第二个解决方案提供另一个解决方案。 我给出的选择是“A)使用“执行事件”的选定对象(检查一下,它包含很多信息)。B)你可以使用 AbstractSourceProvider,所以你可以将你的对象传递给应用程序上下文。“

    A) 如果您的对象是树等结构化对象的选择,则可以在您的处理程序中使用:

    MyObject p = (MyObject) ((IStructuredSelection) HandlerUtil.getCurrentSelection(event)).getFirstElement();
    

    B) Source 提供程序的使用有点棘手。主要思想是,您将对象添加到应用程序上下文中。 Eclipse 3.x 的重要 sn-ps 来自我在阅读 this blog 后设置的项目(注意:它是德语,它提供的示例不起作用): 在你的 plugin.xml 添加:

      <extension point="org.eclipse.ui.services">
      <sourceProvider
            provider="com.voo.example.sourceprovider.PersonSourceProvider">
         <variable
               name="com.voo.example.sourceprovider.currentPerson"
               priorityLevel="activePartId">
         </variable>
      </sourceProvider>
    

    设置您自己的 SourceProvider。调用“getCurrentState”,您可以获得该 SourceProvider 的变量(在这种情况下是您的 Person 对象):

    public class PersonSourceProvider extends AbstractSourceProvider{
    
    /** This is the variable that is used as reference to the SourceProvider
     */
    public static final String PERSON_ID = "com.voo.example.sourceprovider.currentPerson";
    private Person currentPerson;
    
    public PersonSourceProvider() {
    
    }
    
    @Override
    public void dispose() {
        currentPerson = null;
    }
    
    **/**
     * Used to get the Status of the source from the framework
     */
    @Override
    public Map<String, Person> getCurrentState() {
        Map<String, Person> personMap = new HashMap<String, Person>();
        personMap.put(PERSON_ID, currentPerson);
        return personMap;
    }**
    
    @Override
    public String[] getProvidedSourceNames() {
        return new String[]{PERSON_ID};
    }
    
    public void personChanged(Person p){
        if (this.currentPerson != null && this.currentPerson.equals(p)){
            return;
        }
    
        this.currentPerson = p;
        fireSourceChanged(ISources.ACTIVE_PART_ID, PERSON_ID, this.currentPerson);
    }
    

    }

    在您的视图中,您注册到 SourceProvider 并将 Object 设置为您要传输到 Handler 的对象。

    public void createPartControl(Composite parent) {
    
        viewer = new TreeViewer(parent);
        viewer.setLabelProvider(new ViewLabelProvider());
        viewer.setContentProvider(new ViewContentProvider());
        viewer.setInput(rootPerson);
        getSite().setSelectionProvider(viewer);
        viewer.addSelectionChangedListener(new ISelectionChangedListener() {
            @Override
            public void selectionChanged(SelectionChangedEvent event) {
                Person p = null;
                if (event.getSelection() instanceof TreeSelection) {
                    TreeSelection selection = (TreeSelection) event.getSelection();
                    if (selection.getFirstElement() instanceof Person) {
                        p = (Person) selection.getFirstElement();
                    }
                }
                if (p==null) {
                    return;
                }
                IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
                ISourceProviderService service = (ISourceProviderService) window.getService(ISourceProviderService.class);
                PersonSourceProvider sourceProvider = (PersonSourceProvider) service.getSourceProvider(PersonSourceProvider.PERSON_ID);
                sourceProvider.personChanged(p);
            }
        });
    }
    

    在您的处理程序中,您只需调用 PersonSourceProvider#getCurrentState 即可取回您的对象。

    这种方法的优点是,你可以在任何你想要的地方使用 Objectd。例如。您甚至可以设置一个 PropertyTester 来根据当前选择的对象启用/禁用 UI 元素。

    【讨论】:

    • about A 你是怎么传参数的?例如 yObject p = (MyObject) ((IStructuredSelection) HandlerUtil.getCurrentSelection(event)).getFirstElement();你是如何传递 MYObject 的?
    • 我不必明确地通过它。例如,您可以右键单击 TreeItem 并使用下拉菜单调用命令。然后活动选择与事件一起传递,根本不需要调用 ParameterizedCommand。你可以使用这样的常规命令。
    【解决方案2】:

    参数化命令只接受字符串。 以下是较小对象的示例:

    免责声明:这是针对 Eclipse 3.x 的。我没有经常使用 Eclipse 4.x,所以你可能需要适应那里以备不时之需。

    创建一个带有视图 (com.voo.example.commandparameter.advanced.view) 的插件项目 (com.voo.example.commandparameter.advanced) 和一个命令 (com.voo.example.commandparameter.advanced.sysoCommand)菜单项和Handler(com.voo.example.commandparameter.advanced.sysoCommand),以及一个通用对象(MyTestObject)。

    Command 需要 plugin.xml 中的 Parameter 和 Parametertype 传递给它:

    <extension
         point="org.eclipse.ui.commands">
      <command
            id="com.voo.example.commandparameter.advanced.sysoCommand"
            name="SysoCommand">
         <commandParameter
               id="myObject"
               name="object"
               optional="true"
               typeId="com.voo.example.commandparameter.advanced.testType">
         </commandParameter>
      </command>
      <commandParameterType
            id="com.voo.example.commandparameter.advanced.testType"
            type="com.voo.example.commandparameter.advanced.MyTestObject">
      </commandParameterType>
    

    在 Object 中,您可以设置 name 和 street 等属性,并像这样定义一个 convertToString 方法:

    public String convertToString() {
        return getName() +",,,"+ getStreet();
    }
    

    (你也可以重写 toString 方法。我只是使用该方法将奇怪的分隔符设置为返回的字符串) 在 MyParamterConverter 类中,您可以将其传回:

    public class MyParameterConverter extends AbstractParameterValueConverter {
    
    public MyParameterConverter() {
    
    }
    
    @Override
    public String convertToString(Object parameterValue)
            throws ParameterValueConversionException {
        return parameterValue.toString();
    }
    
    /**
     * This will always create a new object. Just keep that in mind 
     * if you're trying to work with the objects.
     */
    @Override
    public Object convertToObject(String parameterValue)
            throws ParameterValueConversionException {
    
        //Split the String to get the attributes back
        String delimiter =",,,";
        String[] split = parameterValue.split(delimiter);
        String name = split[0];
        String street = split [1];
    
        return new MyTestObject(name, street);
    }
    }
    

    现在您可以在视图中通过单击按钮来调用命令,例如:

        btnGo.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent event) {
    
                MyTestObject testObject = new MyTestObject(textName.getText(),textStreet.getText());
    
                ICommandService cS = (ICommandService)getSite().getService(ICommandService.class);
                IHandlerService hS = (IHandlerService)getSite().getService(IHandlerService.class);
    
                Command sysoComm = cS.getCommand("com.voo.example.commandparameter.advanced.sysoCommand");
    
    
                HashMap<String, String> params = new HashMap<String, String>();
                params.put("myObject", testObject.convertToString());
    
                ParameterizedCommand pC = ParameterizedCommand.generateCommand(sysoComm, params);
    
                try {
                    hS.executeCommand(pC, null);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    

    并且Handler可以将传入的参数转换回来:

    public class MyObjectHandler extends AbstractHandler {
    
    @Override
    public Object execute(ExecutionEvent event) throws ExecutionException { 
        String param1 = event.getParameter("myObject");
        MyParameterConverter converter = new MyParameterConverter();
        Object convertToObject = null;
    
        try {
            convertToObject = converter.convertToObject(param1);
        } catch (ParameterValueConversionException e) {
            e.printStackTrace();
        }
    
        if (convertToObject instanceof MyTestObject) {
            MyTestObject to = (MyTestObject) convertToObject;
            System.out.println(to.toString());
        }
    
        return null;
    }
    }
    

    这应该适用于大多数在您传递时不会改变的较小尺寸的对象。如果您需要传递更大的对象,您将有两种选择:A)使用“执行事件”的选定对象(检查一下,它包含很多信息)。 B) 您可以使用 AbstractSourceProvider,因此您可以将您的对象传递给应用程序上下文。

    【讨论】:

    • 哦,还有一篇关于该主题的旧日食论坛帖子:eclipse.org/forums/index.php/t/155586
    • 感谢您的回答,我需要传递更大的对象。我不明白你的选择。能给我举个例子吗?
    【解决方案3】:

    长期以来,我一直专注于通过命令参数传递对象。但最后,最简单的解决方法是简单地忽略参数内容并将所需对象放入新的子 IExclipseContext 并使用该上下文执行命令。这样,您的处理程序就会注入您的对象。

    来电者:

    ECommandService commandService = // get commandService...
    EHandlerService handlerService = // get handlerService...
    IEclipseContext context = // get active or application context...
    
    IEclipseContext childCtx = context.createChild();
    childCtx.set(MyObject.class, instancOfMyObject);
    
    ParameterizedCommand command = commandService.createCommand("my.command.id", null);
    handlerService.executeHandler(command, childCtx);
    

    在您的处理程序中:

    @Execute
    public void execute(@Optional MyObject myObject) {
      if(myObject != null) {
        // work with your object
      }
    }
    

    瞧,不需要转换器或回调(即 SelectionService)...

    【讨论】:

      【解决方案4】:

      我对此并不十分熟悉,因为将参数传递给命令非常罕见。看来您必须在org.eclipse.ui.commands 命令定义中使用commandParameterType 来定义基于AbstractParameterValueConverter 的代码,以在对象和参数值的字符串之间进行转换。

      【讨论】:

      • 我试过了,我创建了从 AbstractParameterValueConverter 扩展的类 myConvert 并创建了 commandParameterType 。我在 myConvert 类中从 String 转换为 Object 但是当我到达目标时,参数总是以 String
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-22
      • 2016-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多