Наследование интерфейса и приведение - PullRequest
4 голосов
/ 06 августа 2010

Я создал интерфейс, который я наследую от другого (COM) интерфейса:

public interface IDTSComponentMetaData : IDTSComponentMetaData90 { }

Это все, что он делает.

Причиной этого является то, что в зависимости от версии SQL Server, с которой я работаю, база может быть IDTSComponentMetaData90 (2005) или IDTSComponentMetaData100 (2008). Вместо того, чтобы условно компилировать каждую ссылку на код IDTSComponentMetaData90 / IDTSComponentMetaData100 в коде, я хотел бы использовать интерфейс, независимый от версии, который просто обернет правильный реальный интерфейс.

Проблема в том, что SSIS передает мне объект в собственный интерфейс в одной ключевой точке, и мне нужно привести его к моему интерфейсу оболочки:

#if SQL2005
public void Initialize(IDTSComponentMetaData90 c,IServiceProvider s) {
#elif SQL2008
public void Initialize(IDTSComopnentMetaData100 c,IServiceProvider s) {
#endif
  m_ComponentMetaData = (IDTSComponentMetaData) c;
  m_ServiceProvider = s;
}

Это компилируется без проблем, но во время выполнения я получаю сообщение «Невозможно привести объект COM типа System .__ ComObject» к типу интерфейса «MyNameSpace.IDTSComponentMetaData». Эта операция завершилась неудачно, поскольку вызов QueryInterface в компоненте COM для интерфейса с IID '{483E01E7-001C-35E4-Ac9f-4B0C1B81E409}' завершился ошибкой из-за следующей ошибки: такой интерфейс не поддерживается (Исключение из HRESULT: 0x80004002 (E_NOINTERFACE)) .

Что я делаю совершенно неправильно?

Ответы [ 4 ]

5 голосов
/ 06 августа 2010

По какой причине вы не просто называете интерфейс в зависимости от версии SQL Server?

#if SQL2005
using IDTSComponentMetaData = IDTSComponentMetaData90;
#elif SQL2008
using IDTSComponentMetaData = IDTSComopnentMetaData100;
#endif
1 голос
/ 06 августа 2010

К сожалению, то, что вы пытаетесь сделать, не сработает.

Проблема в том, что базовый объект фактически не реализует ваш интерфейс. Он реализует только конкретный версионный интерфейс, от которого вы пытаетесь уйти.

Поэтому, когда вы приведете свой объект к этому интерфейсу, он потерпит неудачу.

Лучшее, что вы можете сделать в C #, это создать псевдонимы для интерфейса, но, к сожалению, это нужно делать в верхней части каждого файла .cs, который должен использовать этот интерфейс.

Есть ли шанс, что вы могли бы создать объект-оболочку, который бы реализовал ваш интерфейс? Тогда ваш собственный объект будет реализовывать новый интерфейс и передавать каждый вызов обратно соответствующему методу / свойству базового объекта. В этом объекте вы можете делать все виды #if и аналогичные для обработки различий, но скрывая различия от остальной части вашей программы.

Или вы можете создать два класса, оба реализующих ваш новый интерфейс, и использовать контейнер IoC или аналогичный для запроса «того объекта, который реализует этот интерфейс», не зная, с каким из двух вы на самом деле разговариваете.

0 голосов
/ 06 августа 2010

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

#if SQL2005

[ComImport]
[Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDTSComponentMetaData
{
    // all members of IDTSComponentMetaData90
}

#elif SQL2008

[ComImport]
[Guid("YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDTSComponentMetaData
{
    // all members of IDTSComponentMetaData100
}

#endif
0 голосов
/ 06 августа 2010

сопоставление имен интерфейсов COM с идентификаторами интерфейсов (IID);эта ошибка говорит вам, что объект, с которым вы работаете, не поддерживает IDTSComponentMetaData90.

Я бы сказал, что вам лучше всего здесь явно определить IDTSComponentMetaData, а не выводить его из IDTSComponentMetaData90.Затем можно создать 2 разных класса, которые реализуют интерфейс, перенаправив вызовы методов в интерфейс COM, соответствующий версии SQL Server.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...