Como fazer downcast corretamente em C # com uma interface gerada pelo SWIG?

Eu tenho uma base de código C ++ muito grande e madura para a qual estou tentando usar o SWIG para gerar uma interface C #. Não posso alterar o código C ++ real em si, mas podemos usar o que o SWIG oferece para estendê-lo / atualizá-lo. Estou enfrentando um problema em que uma função C ++ que está escrita como abaixo está causando problemas em c #.

A* SomeClass::next(A*)

O chamador pode fazer algo como:

A* acurr = 0;
while( (acurr = sc->next(acurr)) != 0 ){
    if( acurr isoftype B ){
        B* b = (B*)a;
        ...do some stuff with b..
    }
    elseif( acurr isoftype C )
    ...
}

Essencialmente, iterando através de um contêiner de elementos que, dependendo do seu tipo real, fazem algo diferente. Infelizmente, a camada C # gerada pelo SWIG para a função "next" faz o seguinte:

return new A();

Portanto, o código de chamada em C # não pode determinar se o objeto retornado é realmente uma classe derivada ou não; na verdade, parece ser sempre a classe base (o que faz sentido). Encontrei várias soluções:

Use a palavra-chave% extend SWIG para adicionar um método a um objeto e, finalmente, chamar dynamic_cast. A desvantagem dessa abordagem, a meu ver, é que isso exige que você conheça a hierarquia de herança. No meu caso, é bastante grande e vejo isso como um problema de manutenção.Use a palavra-chave% factory para fornecer o método e os tipos derivados e fazer com que SWIG gere automaticamente o código dynamic_cast. Essa parece ser uma solução melhor que a primeira, porém, com uma análise mais aprofundada, ainda é necessário procurar todos os métodos e todos os tipos derivados possíveis que podem retornar. Novamente, um enorme problema de manutenção. Eu gostaria de ter um link de documento para isso, mas não consigo encontrar um. Eu descobri essa funcionalidade examinando o código de exemplo que acompanha o SWIG.Crie um método C # para criar uma instância do objeto derivado e transfira o cPtr para a nova instância. Embora eu considere isso desajeitado, ele funciona. Veja um exemplo abaixo.
    public static object castTo(object fromObj, Type toType)
    {
        object retval = null;

        BaseClass fromObj2 = fromObj as BaseClass;
        HandleRef hr = BaseClass.getCPtr(fromObj2);
        IntPtr cPtr = hr.Handle;
        object toObj = Activator.CreateInstance(toType, cPtr, false);

        // make sure it actually is what we think it is
        if (fromObj.GetType().IsInstanceOfType(toObj))
        {
            return toObj;
        }

        return retval;
    }

Essas são realmente as opções? E se eu não estiver disposto a pesquisar todas as funções existentes e derivações de classe, então fico com o # 3? Qualquer ajuda seria apreciada.

questionAnswers(3)

yourAnswerToTheQuestion