4

私は Spring4D フレームワークに非常に慣れていないので、助けを求めます。

私は次のクラスとインターフェースを持っています:

ICommand = interface

TCommand = class(TInterfacedObject, ICommand)

IVecadCommand = interface(ICommand)

TVecadCommand = class(TCommand, IVecadCommand)

TVecadCommandJPG = class(TVecadCommand, IVecadCommand)

TCommandDeckelJPG = class(TVecadCommandJPG, IVecadCommand)

次に、コンポーネントを登録します。

GlobalContainer.RegisterComponent<TCommandDeckelJPG>.Implements<IVecadCommand>('deckel_jpg');

次に、ServiceLocator を使用してオブジェクトを作成しようとします。

var
  i: Integer;
  com: ICommand;
begin
  Result := nil;
  com := ServiceLocator.GetService<ICommand>(actionName);
  com.setSession(designSession);
  Result := com;
end;

実行の結果、例外があります。

Invalid class typecast

例外を回避するために、次のようにします。

var
  i: Integer;
  com: IVecadCommand;
begin
  Result := nil;
  com := ServiceLocator.GetService<IVecadCommand>(actionName);
  com.setSession(designSession);
  Result := com;
end;

その後、すべてがOKです。

ポイントは、この場合、TCommand および継承されたクラスのリポジトリとして TContainer を使用する必要があることです。したがって、最初に ServiceLocator を使用する必要があります。

例外を回避し、TContainer で IVecadCommand ではなく ICommand を使用するにはどうすればよいですか?

ありがとう。喜んで追加の詳細を提供します。

4

1 に答える 1

6

登録IVecadCommandしましたが、 を要求しましたICommand

エラーは誤解を招くものであり、実際には、それを解決する方法がわからないことを示す例外が発生するはずです (バグのようです - 私はそれを調べます)。

これは、明示的に登録したサービスのみを要求できるためです。継承チェーンは検索しません。

クラスを解決できるようにしたい場合は、登録ICommandに別のクラスを追加する必要があります。.Implements<ICommand>名前は一意である必要があり、おそらく名前で解決したいので、 とは異なる名前を付ける必要がありIVecadCommandます。として解決したくない場合IVecadCommand( として解決したら、サポートを使用できますICommand)、既存の登録を からIVecadCommandに変更するだけICommandです。

編集: 私は実際には完全に正しくありませんでした-名前で解決すると、コンテナーは渡されたタイプをチェックしません。この場合の問題は、によって行われるIVecadCommandへの変換です。しかし、それは正しく処理されません。今後のバージョンで修正します。まだ方法がわかりません。一貫性を保つために、ここでも型について厳密にする必要があります。とにかく、今のところ問題を解決するために上で述べたことを実行すれば、あなたは安全です.ICommandTValue.AsType<T>

更新 10.04.2014: この問題を修正したので、解決されたものの親インターフェイスを取得する名前付き解決を実行できるようになりました。

于 2014-04-01T00:11:02.160 に答える