2014-03-31 1 views
4

Я очень новичок в рамках Spring4D и прошу помощи.Как получить экземпляр дочернего интерфейса из ServiceLocator в 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; 

тогда все в порядке.

Точка: я должен использовать его TContainer в этом случае как репозиторий для TCommand и унаследованных классов. Поэтому я должен сначала использовать ServiceLocator.

Что делать, чтобы избежать исключения и использовать ICommand, но не IVecadCommand в TContainer?

Спасибо. С удовольствием предоставит вам дополнительную информацию.

ответ

6

Вы зарегистрированы IVecadCommand, но запросили у ICommand.

Ошибка является вводящей в заблуждение, и на самом деле она должна была вызвать исключение, сообщая вам, что она не знает, как это решить (похоже, ошибка - я буду изучать это).

Это потому, что вы можете запрашивать только те услуги, которые вы зарегистрировали явно. Он не ищет цепочку наследования.

Если вы хотите, чтобы иметь возможность решить этот вопрос так же, как ICommand, вам нужно добавить еще один .Implements<ICommand>. Поскольку имена должны быть уникальными, и вы, вероятно, хотите разрешить их по имени, вы должны дать ему другое имя, чем IVecadCommand. Если вы не хотите разрешать его как IVecadCommand (вы можете использовать оповещения после того, как вы определились как ICommand), то просто измените существующую регистрацию с IVecadCommand на ICommand.

Редактировать: Я действительно был не совсем прав - при разрешении по имени контейнер не проверяет пройденный тип. В этом случае проблема заключается в преобразовании IVecadCommand в ICommand, которое делается по TValue.AsType<T>. Но это неправильно. Я исправлю это в следующей версии. Я пока еще не знаю. Для согласованности он также должен быть строгим по типу. В любом случае, если вы сделаете то, что я сказал выше, чтобы решить проблему, пока вы в безопасности.

Update 10.04.2014: Я сделал исправить эту проблему, так что теперь это должно быть возможно сделать именованный решительность, получая обратно родительский интерфейс разрешенном один.

+0

Да, я нашел то же самое решение. Большое спасибо. – mad

 Смежные вопросы

  • Нет связанных вопросов^_^