2016-04-25 6 views
0

99%3.x APIで構成されているLunaをベースにした既存のEclipse RCPで作業しています。我々は進行中のプロセスでこれを変更したい。新しいビューを作成する作業が与えられたとき、私はorg.eclipse.ui.views拡張ポイントの新しい(ルナでは、とにかく)e4view要素を使いたいと思っていました。Guice注入でe4viewを挿入する方法

私の問題は、RCPの一部がxtextを使用しているため、Guiceを使用していくつかのコンポーネントを利用できることです。

<plugin> 
    <extension 
     point="org.eclipse.ui.views"> 
     <e4view 
      class="my.app.MyExecutableExtensionFactory:my.app.MyViewPart" 
      id="my.app.view" 
      name="my view" 
      restorable="true"> 
     </e4view> 
    </extension> 
</plugin> 

:私は今、これはGuiceのを注入取得するには、この

public class MyViewPart 
{ 
    @Inject // <- should be injected via Guice (I used @com.google.inject.Inject, otherwise E4DI would complain) 
    ISomeCustomComponent component; 

    @PostConstruct // <- should be called and injected via E4 DI 
    public void createView(Composite parent) 
    { 
     // ... 
    } 
} 

ようなもので撚りい

、私は通常、このようなAbstractGuiceAwareExecutableExtensionFactoryを(通常のXtextコンテキストで行われるように)使用しますしかし、私はE4の仕組みをバイパスすると思っていたので、これがうまくいくとは思っていませんでした(実際には、それは他の方法と思われます)、そして、e4view.class要素が拡張機能を無視して、にE4DIを注入します。確かに、クラスロードブレークポイントをContextInjectionFactory.make()からヒットしたMyViewPartに設定しました。

私が言ったように、私は両方のDIフレームワークが矛盾なく共存することを期待していなかったので、私の問題の解決策は、私が注入する必要があるオブジェクトをE4コンテキストに入れることだと思います。

私はちょっとグーグルではありますが、私は複数のアプローチを見つけました。どれが「正しい」か「良い」かはわかりません。私が発見したアプローチの中で

は、あります

  1. はGuiceのからオブジェクトを取り出すコンテキスト機能Guiceのインジェクタにデリゲート
  2. を提供してからオブジェクトを取り出すインジェクタバインディング
  3. として、それらを設定しますguice、文脈を取得して文脈に入れる

(最初の2つのアプローチは、の「バインディングの構成」セクションに記載されています。)

そしてもちろん、私はMyViewPart実装でGuiceのからオブジェクトを得ることができるが、それは私が欲しいものではありません...

[編集:]私は上記のオプションを検討している一方より多くのビット:

コンテキスト

機能は、私は、このユーティリティメソッドを持つバンドルアクティベータでサービスとしてコンテキスト機能を登録しようとしました:

private void registerGuiceDelegatingInjection(final BundleContext context, final Class<?> clazz) 
{ 
IContextFunction func = new ContextFunction() 
{ 
    @Override 
    public Object compute(final IEclipseContext context, final String contextKey) 
    { 
    return guiceInjector.getInstance(clazz); 
    } 
}; 

ServiceRegistration<IContextFunction> registration = 
    context.registerService(IContextFunction.class, func, 
    new Hashtable<>(Collections.singletonMap(
    IContextFunction.SERVICE_CONTEXT_KEY, clazz.getName() 
))); 
} 

BundleActivatorのstart()メソッドでregisterGuiceDelegatingInjection()というメソッドをGuiceから取得する必要があるクラスごとに呼びました。

何らかの理由でこれが機能しませんでした。サービス自体は期待どおりに登録されていましたが(OSGiコンソールでチェックしましたが)、コンテキスト・ファンクションは呼び出されませんでした。代わりに私は注射中にオブジェクトが見つからないという注入エラーが出ています。おそらく、コンテキスト関数は動的に寄与することはできませんが、宣言型サービスを介して寄与しなければならないことがあるため、プラットフォームが始動するとすぐにわかります。

(ここで回答です:はいIContextFunctionへのJavaDocが言うように:コンテキスト関数は、必要に応じて初期値とコンテキストのインスタンスをシードする[...] OSGiサービスとして登録することができます - とアプリケーション・コンテキストがすでに存在しているため。私のバンドルが起動されると、動的に登録されたサービスは、ContextFactoryには表示されません)。

インジェクターバインディング

あなただけあなたが

 InjectorFactory.getDefault().addBinding(IMyComponent.class).implementedBy(MyComponent.class) 

形で実装クラスへのマッピングインターフェース・クラスを指定することができますので、私はすぐに、このソリューションは、私のために動作しないことが判明明らかにインスタンスやファクトリをこのように構成することはできないので、これはオプションではありません。私はGuiceに委任し、Guiceがターゲットクラスのインスタンスを取得する必要があるからです...

オブジェクトをコンテキストに置く

これは現在私にとってはうまくいくが、あまりうまくいかない。以下の回答を参照してください。

[編集2:]私が報告したように、(アプリケーション)コンテキストでオブジェクトを配置することは私の仕事です。欠点は、アプリケーションコンテキストでオブジェクトを持つことがあまりにもグローバルであることです。別のDSLにオブジェクトインスタンスを注入する必要があるバンドルが2つ以上ある場合、間違ったインスタンスを注入しないように注意しなければなりません(例えば、@Namedアノテーションを使用して)。

私は、e4viewが作成され、直接注入されるPartのコンテキストを拡張する方法をお勧めします。しかし、これまでのところ、私は...それ以上のヒントについて

感謝を私のインスタンスに入れたときに、明示的にそのコンテキストをターゲットにする方法を発見していない...

答えて

1

は、E4のプロセッサメカニズムを試してみてください:あなたが使用する必要がありますPOJOを(グローバル)IEclipseContextに登録するために、(PostまたはPost)Processor(PostContextCreateアノテーションとともに)を使用します。

+0

あなたの答えをありがとう。しかし、ドキュメントを正しく理解していれば、 '@ PostContextCreate'を使うために、アプリケーション/製品に' lifeCycleURI'プロパティを追加する必要があります。 (少なくともこれはhttp://www.vogella.com/tutorials/Eclipse4LifeCycle/article.htmlに記載されています)。これは私にはあまりにもグローバルなようだが、バンドルに基づいて構築しているいくつかの製品があり、すべての製品を変更したくない。 –

0

これまでのところ私にとって最も効果的だった解決策は、バンドルアクチベータのstart()メソッドの間にIEclipseContextを取得して、必要なクラスを自分自身に配置することでした。

private void registerGuiceDelegatingInjection(final BundleContext context, final Class<?> clazz) 
{ 
    IServiceLocator s = PlatformUI.getWorkbench(); 
    IEclipseContext ctx = (IEclipseContext) s.getService(IEclipseContext.class); 
    ctx.set(clazz.getName(), guiceInjector.getInstance(clazz)); 
} 

これは少なくとも現在は機能しています。より多くのバンドルがインスタンスを直接コンテキストに入れると、将来どのように動作するかわかりません。おそらく長期的な名前のインスタンスで必要になるでしょう。また、私にとっては、注入されたオブジェクトがシングルトンであるため、これは機能します。したがって、単一のインスタンスをコンテキストに入れることに何の害も及ぼしません。

私はコンテクスト関数の方が良いと思っていましたが、これまでのところうまくいきませんでした。

関連する問題