RCW (Runtime Callable Wrapper)
O common language runtime expõe objetos COM através de um proxy chamado RCW (Runtime Callable Wrapper). Embora o RCW pareça ser um objeto comum para clientes .NET, a função principal dele é realizar marshaling de chamadas entre um cliente .NET e um objeto COM.
O runtime cria exatamente um RCW para cada objeto COM, independentemente do número de referências que existem nesse objeto. O runtime mantém um único RCW por processo para cada objeto. Se você criar um RCW em um domínio de aplicativo ou apartment e, em seguida, passar uma referência a outro domínio de aplicativo ou apartment, um proxy para o primeiro objeto será usado. Observe que esse proxy é um novo objeto gerenciado e não o mesmo que o RCW inicial; isso significa que os dois objetos gerenciados não são iguais, mas representam o mesmo objeto COM. Conforme mostra a ilustração a seguir, qualquer número de clientes pode conter uma referência a objetos COM que expõem interfaces INew
e INewer
.
A seguinte imagem mostra o processo para acessar objetos COM por meio do RCW (Runtime Callable Wrapper):
Usando metadados derivados de uma biblioteca de tipos, o runtime cria o objeto COM que está sendo chamado e um wrapper para esse objeto. Cada RCW mantém um cache de ponteiros de interface no objeto COM que ele encapsula e, além disso, libera sua referência no objeto COM quando o RCW não é mais necessário. O runtime executa a coleta de lixo no RCW.
Entre outras atividades, o RCW realiza marshaling de dados entre código gerenciado e não gerenciado, em nome do objeto encapsulado. Especificamente, o RCW fornece marshalling para argumentos de método e valores retornados do método sempre que o cliente e o servidor têm representações diferentes dos dados transmitidos entre eles.
O wrapper padrão impõe regras de marshalling internas. Por exemplo, quando um cliente .NET passa um tipo de string
como parte de um argumento para um objeto não gerenciado, o wrapper converte a string
em um tipo BSTR
. Se o objeto COM retornar um BSTR
ao chamador gerenciado, o chamador receberá uma string
. Tanto o cliente quanto o servidor enviam e recebem dados com os quais estão familiarizados. Outros tipos não exigem conversão. Por exemplo, um wrapper padrão sempre passará um inteiro de 4 bytes entre código gerenciado e não gerenciado sem converter o tipo.
Marshalling de interfaces selecionadas
A meta principal do RCW (Runtime Callable Wrapper) é ocultar as diferenças entre os modelos de programação gerenciado e não gerenciado. Para criar uma transição suave, o RCW consome interfaces COM selecionadas sem expô-las ao cliente .NET, conforme mostrado na ilustração a seguir.
A seguinte imagem mostra as interfaces COM e o RCW (Runtime Callable Wrapper):
Quando criado como um objeto associado precocemente, o RCW é um tipo específico. Ele implementa as interfaces que o objeto COM implementa e expõe os métodos, propriedades e eventos das interfaces do objeto. Na ilustração, o RCW expõe a interface INew mas consome as interfaces IUnknown e IDispatch. Além disso, o RCW expõe todos os membros da interface INew para o cliente .NET.
O RCW consome as interfaces listadas na tabela a seguir, as quais são expostas pelo objeto que ele encapsula.
Interface | Descrição |
---|---|
IDispatch | Para associação tardia a objetos COM por meio de reflexão. |
IErrorInfo | Fornece uma descrição textual do erro, sua origem, um arquivo de Ajuda, um contexto de Ajuda e o GUID da interface que definiu o erro (sempre GUID_NULL para classes do .NET). |
IProvideClassInfo | Se o objeto COM sendo empacotado implementa IProvideClassInfo, o RCW extrai as informações de tipo dessa interface para fornecer uma melhor identidade de tipo. |
IUnknown | Para gerenciamento do tempo de vida, coerção de tipo e identidade de objeto: – Identidade do objeto O runtime faz distinção entre os objetos COM, comparando o valor da interface IUnknown para cada objeto. – Coerção de tipo O RCW reconhece a descoberta de tipo dinâmico executada pelo método QueryInterface. – Gerenciamento do tempo de vida Usando o QueryInterface método RCW obtém e mantém uma referência a um objeto não gerenciado até o runtime executar a coleta de lixo no wrapper, que libera o objeto não gerenciado. |
O RCW, opcionalmente, consome as interfaces listadas na tabela a seguir, as quais são expostas pelo objeto que ele encapsula.
Interface | Descrição |
---|---|
IConnectionPoint e IConnectionPointContainer | O RCW converte objetos que expõem o estilo do evento de ponto de conexão para eventos com base em delegado. |
IDispatchEx (somente .NET Framework) | Se a classe implementa IDispatchEx, o RCW implementa IExpando. A interface IDispatchEx é uma extensão da interface IDispatch que, ao contrário de IDispatch, permite a enumeração, adição, exclusão e chamada de membros que diferencia maiúsculas de minúsculas. |
IEnumVARIANT | Permite que os tipos COM que dão suporte a enumerações sejam tratados como coleções. |