如何在命令中传递对象参数?

时间:2023-01-14 12:09:12

I created an eclipse-rcp's project's plugin.xml with a new command with a parameter.

我创建了一个eclipse-rcp项目的插件。带有参数的新命令的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);

I tried this example to pass parameters and it worked.

我试过这个例子来传递参数,它起作用了。

The issue in this example that I could pass only parameters of type String. ( because Parameterization )

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

I want to pass parameter of hash map and in general to pass any object.

我想要传递哈希映射的参数,并在一般情况下传递任何对象。

I tried this code

我试着这段代码

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




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

but it didn't work the parameters didn't move ( it was null)

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

Could you please help to to move object as parameter in command ?

你能帮忙把物体作为参数移动到命令里吗?

3 个解决方案

#1


3  

Since it would get confusing to add another solution to my first answer, I'll provide another one for a second solution. The choices I gave were " A) use the selected object of the "Execution Event" (examine that, it contains a lot of infos). B) you can use AbstractSourceProvider, so you can pass your object to the application context."

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

A) can be used in your Handler if your object is the selection of a Structured Object like a Tree:

如果对象是像树这样的结构化对象的选择,则可以在处理程序中使用它:

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

B) The usage of a Source provider is a bit more tricky. The main idea is, that you add your object to the application context. The important snippets for Eclipse 3.x from a project that I set up after I read this blog (note: it is in german and the example it provides doesn't work): In your plugin.xml add:

B)源提供程序的使用有点棘手。主要思想是,将对象添加到应用程序上下文。Eclipse 3的重要片段。我在阅读完这个博客后建立的一个项目(注意:它是德语的,它提供的例子不适用):在你的插件中。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>

Set up your own SourceProvider. Calling the "getCurrentState" you can get the variable (your Person object in this case) of that 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);
}

}

}

In your View you register to the SourceProvider and set the Object to the object you want to transfer to your Handler.

在您的视图中,您向SourceProvider注册,并将对象设置为您想要传输到处理程序的对象。

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);
        }
    });
}

And in your Handler you can just call the PersonSourceProvider#getCurrentState to get your Objects back.

在您的处理程序中,您可以调用PersonSourceProvider#getCurrentState来将对象返回。

Advantage of this method is, that you can use the Objectd anywhere you want. E.g. you can even set up a PropertyTester to enable/disable UI elements according to the currently selected Object.

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

#2


2  

The Parameterized Command does only accept Strings. Here is an example for smaller objects:

参数化命令只接受字符串。这里有一个小物件的例子:

Disclaimer: this is for Eclipse 3.x. I am not using Eclipse 4.x a lot, so you might have to adapt there in case you need it.

免责声明:这是针对Eclipse 3.x的。我没有使用Eclipse 4。x很多,所以你可能需要适应那里,以防你需要它。

Create a Pluginproject (com.voo.example.commandparameter.advanced) with a View (com.voo.example.commandparameter.advanced.view) , a Command (com.voo.example.commandparameter.advanced.sysoCommand) with menu entry and Handler(com.voo.example.commandparameter.advanced.sysoCommand), and a universal Object (MyTestObject).

创建一个插件项目(com.voo.example.commandparameter.advanced)和一个视图(com.voo.example.commandparameter.advanced. View),一个命令(com.voo.example.commandparameter.advanced.sysoCommand)和菜单条目和处理程序(com.voo.example.commandparameter.advanced.sysoCommand)和一个通用对象(MyTestObject)。

The Command needs a Parameter and a Parametertype in the plugin.xml, that gets passed to it:

该命令需要一个参数和一个参数类型的插件。xml被传递给它:

<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>

In the Object you set atrtibutes like name and street and define a convertToString method like that:

在对象中,您设置了像名称和街道的atrtibutes,并定义了一个convertToString方法:

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

(you can override the toString method, too. I just used that method to set weired delimiters to the returned String) And in a Class MyParamterConverter you can transfer it back:

(您也可以重写toString方法。我只是用这个方法将weired分隔符设置为返回的字符串),在一个类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);
}
}

Now you can call the command with a buttonclick in your view, for example:

现在,您可以在视图中使用buttonclick来调用该命令,例如:

    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();
            }
        }
    });

And the Handler can transform the passed parameters back :

并且处理程序可以将传递的参数转换回:

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;
}
}

This should work for most smaller sized objects that do not change while you pass them. If you need to pass bigger objects, you will have two choices: A) use the selected object of the "Execution Event" (examine that, it contains a lot of infos). B) you can use AbstractSourceProvider, so you can pass your object to the application context.

这应该适用于大多数较小的对象,当您通过它们时它们不会发生变化。如果您需要传递更大的对象,您将有两个选择:A)使用“执行事件”的选定对象(检查该对象,它包含许多信息)。您可以使用AbstractSourceProvider,这样您就可以将对象传递给应用程序上下文。

#3


0  

I am not really familiar with this as passing parameters to commands is quite rare. It looks like you have to use commandParameterType in the org.eclipse.ui.commands command definition to define code based on AbstractParameterValueConverter to convert between objects and the string for the parameter value.

我不太熟悉这个,因为将参数传递给命令非常少见。看起来,您必须在org.eclipse.ui.command定义中使用commandParameterType来定义基于AbstractParameterValueConverter的代码,以在对象和字符串之间转换参数值。

#1


3  

Since it would get confusing to add another solution to my first answer, I'll provide another one for a second solution. The choices I gave were " A) use the selected object of the "Execution Event" (examine that, it contains a lot of infos). B) you can use AbstractSourceProvider, so you can pass your object to the application context."

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

A) can be used in your Handler if your object is the selection of a Structured Object like a Tree:

如果对象是像树这样的结构化对象的选择,则可以在处理程序中使用它:

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

B) The usage of a Source provider is a bit more tricky. The main idea is, that you add your object to the application context. The important snippets for Eclipse 3.x from a project that I set up after I read this blog (note: it is in german and the example it provides doesn't work): In your plugin.xml add:

B)源提供程序的使用有点棘手。主要思想是,将对象添加到应用程序上下文。Eclipse 3的重要片段。我在阅读完这个博客后建立的一个项目(注意:它是德语的,它提供的例子不适用):在你的插件中。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>

Set up your own SourceProvider. Calling the "getCurrentState" you can get the variable (your Person object in this case) of that 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);
}

}

}

In your View you register to the SourceProvider and set the Object to the object you want to transfer to your Handler.

在您的视图中,您向SourceProvider注册,并将对象设置为您想要传输到处理程序的对象。

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);
        }
    });
}

And in your Handler you can just call the PersonSourceProvider#getCurrentState to get your Objects back.

在您的处理程序中,您可以调用PersonSourceProvider#getCurrentState来将对象返回。

Advantage of this method is, that you can use the Objectd anywhere you want. E.g. you can even set up a PropertyTester to enable/disable UI elements according to the currently selected Object.

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

#2


2  

The Parameterized Command does only accept Strings. Here is an example for smaller objects:

参数化命令只接受字符串。这里有一个小物件的例子:

Disclaimer: this is for Eclipse 3.x. I am not using Eclipse 4.x a lot, so you might have to adapt there in case you need it.

免责声明:这是针对Eclipse 3.x的。我没有使用Eclipse 4。x很多,所以你可能需要适应那里,以防你需要它。

Create a Pluginproject (com.voo.example.commandparameter.advanced) with a View (com.voo.example.commandparameter.advanced.view) , a Command (com.voo.example.commandparameter.advanced.sysoCommand) with menu entry and Handler(com.voo.example.commandparameter.advanced.sysoCommand), and a universal Object (MyTestObject).

创建一个插件项目(com.voo.example.commandparameter.advanced)和一个视图(com.voo.example.commandparameter.advanced. View),一个命令(com.voo.example.commandparameter.advanced.sysoCommand)和菜单条目和处理程序(com.voo.example.commandparameter.advanced.sysoCommand)和一个通用对象(MyTestObject)。

The Command needs a Parameter and a Parametertype in the plugin.xml, that gets passed to it:

该命令需要一个参数和一个参数类型的插件。xml被传递给它:

<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>

In the Object you set atrtibutes like name and street and define a convertToString method like that:

在对象中,您设置了像名称和街道的atrtibutes,并定义了一个convertToString方法:

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

(you can override the toString method, too. I just used that method to set weired delimiters to the returned String) And in a Class MyParamterConverter you can transfer it back:

(您也可以重写toString方法。我只是用这个方法将weired分隔符设置为返回的字符串),在一个类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);
}
}

Now you can call the command with a buttonclick in your view, for example:

现在,您可以在视图中使用buttonclick来调用该命令,例如:

    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();
            }
        }
    });

And the Handler can transform the passed parameters back :

并且处理程序可以将传递的参数转换回:

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;
}
}

This should work for most smaller sized objects that do not change while you pass them. If you need to pass bigger objects, you will have two choices: A) use the selected object of the "Execution Event" (examine that, it contains a lot of infos). B) you can use AbstractSourceProvider, so you can pass your object to the application context.

这应该适用于大多数较小的对象,当您通过它们时它们不会发生变化。如果您需要传递更大的对象,您将有两个选择:A)使用“执行事件”的选定对象(检查该对象,它包含许多信息)。您可以使用AbstractSourceProvider,这样您就可以将对象传递给应用程序上下文。

#3


0  

I am not really familiar with this as passing parameters to commands is quite rare. It looks like you have to use commandParameterType in the org.eclipse.ui.commands command definition to define code based on AbstractParameterValueConverter to convert between objects and the string for the parameter value.

我不太熟悉这个,因为将参数传递给命令非常少见。看起来,您必须在org.eclipse.ui.command定义中使用commandParameterType来定义基于AbstractParameterValueConverter的代码,以在对象和字符串之间转换参数值。