如何在保持松散耦合的情况下通过 Eclipse Selection Service 处理来自不同供应商的选择?
How to process selections from different providers via the Eclipse Selection Service while maintaining loose coupling?
TL;DR:有没有一种方法,最好是遵循设计模式最佳实践,在不破坏松散耦合的情况下处理 ISelectionListener
中来自多个 ISelectionProvider
的 ISelection
,无需猜测(类型检查、转换)?
在我的 Eclipse RCP 3.7 应用程序中,我有两个 views 和一个 (GEF) editor。视图包含清单,允许用户通过 selection 控制编辑器的内容。假设编辑器显示大学教职工层次结构,一个视图将允许 select 应显示教职工的部门,另一个将允许 select 应显示教职工的当前学位级别。
即,如果用户在一个视图中select编辑了计算机科学和英语文学,并且Post-Doc 和 Full Professor* 在另一个中,编辑器会显示人员(如,例如,节点)是 Post-Docs 或 CS 或 EngLit 系的全职教授。但是,该模型包含所有部门的所有员工。
我已经根据 Eclipse Workbench: Using the Selection Service 实现了视图和编辑器:编辑器有一个 org.eclipse.ui.ISelectionListener
,视图都实现了 org.eclipse.jface.viewers.ISelectionProvider
。这些视图维护一个监听器列表,只要 selection 发生变化,就会在循环中通知这些监听器:
((ISelectionChangedListener) listeners.getListeners()[i]).selectionChanged(
新的 SelectionChangedEvent(DeptView.this,
新结构化选择({selection})))
到目前为止,我已经尝试了以下实现,但我对其中任何一个都不满意。
对于 {selection}
,使用自定义 class(例如,DeptSelection
),它封装了 selected 元素,或者更确切地说是模型他们指向的元素。我认为这打破了松耦合,因为DeptSelection
将在部门插件[=66=中定义],它将与 Editor 插件 分开,同时我希望允许客户端添加扩展,其 selection 监听器也可以监听.
对于{selection}
,只需传递selected元素(在本例中通过org.eclipse.jface.viewers.CheckboxTableViewer#getCheckedElements()
),并在ISelectionListener#selectionChanged()
中进行处理编辑。这是笨拙,因为它涉及很多猜测:类型检查、转换等。另外,对于这个解决方案,我然后 "save" select 离子在一个abstract util class SelectionUtil
,在编辑器(这里是根编辑部分的内容编辑部分)中读取,将相应的模型元素添加到 AbtractEditPart
的 [= 返回的列表中23=]。我 (a) 不确定抽象实用程序 class 的使用是否会破坏松耦合 ,以及 (b) 是否有 抽象实用程序 class 是一个很好的设计模式.
因此我的问题是:有没有一种不笨拙的方法,最好是遵循设计模式最佳实践,在不破坏松散耦合的情况下处理多个 ISelection
?
*我知道,这不是最准确的例子,因为 "Full Professor" 和 "Post-Doc" 不完全是度数。
查看 Adapter Pattern, the IAdaptable 界面,并用您的实际对象填充 StructuredSelection,而不是为传达选择而创建的其他容器(您已正确识别为有问题)。
编辑:此外,https://eclipse.org/articles/Article-WorkbenchSelections/article.html
您可以将您放入选择工具中的对象设为 IAdaptable
,这样您就可以查询您真正想要的 class 对象:
MyObject obj = ((IAdaptable)selectionObject).getAdapter(MyObject.class);
您的选择对象将具有:
public Object getAdapter(Class adapter)
{
if (adapter == MyObject.class)
return .... my object instance
return null;
}
您可以更进一步,使用 IAdapterFactory
class,这样您就可以将完全独立的 class 用于适配代码。类似于:
class AdapterFactory implements IAdapterFactory
{
@Override
public Object getAdapter(Object adaptableObject, Class adapterType)
{
if (adaptableObject instanceof MyObject && adapterType == MyObject.class)
{
... convert from 'adaptableObject' to MyObject
return myobject;
}
return null;
}
@Override
public Class<?> [] getAdapterList()
{
return new Class<?> [] {MyObject.class};
}
}
您可以使用适配器管理器或使用 org.eclipse.core.runtime.adapters
扩展点以编程方式声明工厂。
这样您就可以使用适配器管理器从您的选择中找到对象:
MyObject obj = (MyObject)Platform.getAdapterManager().getAdapter(selectionObject, MyObject.class);
Eclipse 本身使用适配器工厂方法将用户界面对象适配为 IFile 之类的对象。
TL;DR:有没有一种方法,最好是遵循设计模式最佳实践,在不破坏松散耦合的情况下处理 ISelectionListener
中来自多个 ISelectionProvider
的 ISelection
,无需猜测(类型检查、转换)?
在我的 Eclipse RCP 3.7 应用程序中,我有两个 views 和一个 (GEF) editor。视图包含清单,允许用户通过 selection 控制编辑器的内容。假设编辑器显示大学教职工层次结构,一个视图将允许 select 应显示教职工的部门,另一个将允许 select 应显示教职工的当前学位级别。
即,如果用户在一个视图中select编辑了计算机科学和英语文学,并且Post-Doc 和 Full Professor* 在另一个中,编辑器会显示人员(如,例如,节点)是 Post-Docs 或 CS 或 EngLit 系的全职教授。但是,该模型包含所有部门的所有员工。
我已经根据 Eclipse Workbench: Using the Selection Service 实现了视图和编辑器:编辑器有一个 org.eclipse.ui.ISelectionListener
,视图都实现了 org.eclipse.jface.viewers.ISelectionProvider
。这些视图维护一个监听器列表,只要 selection 发生变化,就会在循环中通知这些监听器:
((ISelectionChangedListener) listeners.getListeners()[i]).selectionChanged( 新的 SelectionChangedEvent(DeptView.this, 新结构化选择({selection})))
到目前为止,我已经尝试了以下实现,但我对其中任何一个都不满意。
对于
{selection}
,使用自定义 class(例如,DeptSelection
),它封装了 selected 元素,或者更确切地说是模型他们指向的元素。我认为这打破了松耦合,因为DeptSelection
将在部门插件[=66=中定义],它将与 Editor 插件 分开,同时我希望允许客户端添加扩展,其 selection 监听器也可以监听.对于
{selection}
,只需传递selected元素(在本例中通过org.eclipse.jface.viewers.CheckboxTableViewer#getCheckedElements()
),并在ISelectionListener#selectionChanged()
中进行处理编辑。这是笨拙,因为它涉及很多猜测:类型检查、转换等。另外,对于这个解决方案,我然后 "save" select 离子在一个abstract util classSelectionUtil
,在编辑器(这里是根编辑部分的内容编辑部分)中读取,将相应的模型元素添加到AbtractEditPart
的 [= 返回的列表中23=]。我 (a) 不确定抽象实用程序 class 的使用是否会破坏松耦合 ,以及 (b) 是否有 抽象实用程序 class 是一个很好的设计模式.
因此我的问题是:有没有一种不笨拙的方法,最好是遵循设计模式最佳实践,在不破坏松散耦合的情况下处理多个 ISelection
?
*我知道,这不是最准确的例子,因为 "Full Professor" 和 "Post-Doc" 不完全是度数。
查看 Adapter Pattern, the IAdaptable 界面,并用您的实际对象填充 StructuredSelection,而不是为传达选择而创建的其他容器(您已正确识别为有问题)。
编辑:此外,https://eclipse.org/articles/Article-WorkbenchSelections/article.html
您可以将您放入选择工具中的对象设为 IAdaptable
,这样您就可以查询您真正想要的 class 对象:
MyObject obj = ((IAdaptable)selectionObject).getAdapter(MyObject.class);
您的选择对象将具有:
public Object getAdapter(Class adapter)
{
if (adapter == MyObject.class)
return .... my object instance
return null;
}
您可以更进一步,使用 IAdapterFactory
class,这样您就可以将完全独立的 class 用于适配代码。类似于:
class AdapterFactory implements IAdapterFactory
{
@Override
public Object getAdapter(Object adaptableObject, Class adapterType)
{
if (adaptableObject instanceof MyObject && adapterType == MyObject.class)
{
... convert from 'adaptableObject' to MyObject
return myobject;
}
return null;
}
@Override
public Class<?> [] getAdapterList()
{
return new Class<?> [] {MyObject.class};
}
}
您可以使用适配器管理器或使用 org.eclipse.core.runtime.adapters
扩展点以编程方式声明工厂。
这样您就可以使用适配器管理器从您的选择中找到对象:
MyObject obj = (MyObject)Platform.getAdapterManager().getAdapter(selectionObject, MyObject.class);
Eclipse 本身使用适配器工厂方法将用户界面对象适配为 IFile 之类的对象。