Convenções de codificação para a API de metadados
Este tópico discute as convenções de codificação usadas pelos metadados API.
Manipulação de parâmetros de seqüência de caracteres
Os metadados API expõe todas as seqüências de caracteres no formato Unicode. (O formato de disco para nomes de símbolo é realmente o UTF-8, mas que está oculto de clientes da API de metadados). Cada seqüência de caracteres retornada é um triplo de três parâmetros (nomes de parâmetro reais variam):
[in] ULONG cchString -O tamanho, em bytes, do buffer no qual a seqüência de caracteres, incluindo o caractere nulo de terminação, está a ser retornado.
[out] LPCWSTR wzString -um ponteiro para o buffer no qual a seqüência de caracteres é retornada.
[out] ULONG *pchString -um ponteiro para o tamanho da seqüência de caracteres retornada (incluindo o caractere nulo de terminação). Se o buffer é muito pequeno para armazenar a seqüência inteira, a seqüência de caracteres retornada será truncada, uma indicação de erro é retornada e o cliente pode realocar o buffer e repetir se desejado.
Nomes de símbolo
As seguintes convenções se aplicam a nomes de símbolo para parâmetros de seqüência de caracteres:
Seqüência de parâmetros que são nomes de símbolos são sempre considerados terminada por caractere nulo e não por [comprimento in] parâmetro é necessário. Caracteres nulos inseridos não são suportados.
Se um [in] cadeia de caracteres do parâmetro é muito grande para persistir sem truncamento, um erro será retornado.
Seqüências de caracteres do usuário
As seguintes convenções se aplicam aos parâmetros de seqüência de caracteres fornecido pelo usuário:
Seqüências de caracteres de usuário podem ter incorporadas caracteres nulos e não devem ter um terminador nulo.
Um comprimento deve ser fornecido na cchString parâmetro. O tamanho do buffer deve ser o comprimento exato da seqüência de caracteres que será armazenado.
Armazenar os valores padrão
Constantes podem ser armazenados em metadados, como valores padrão para campos, parâmetros e propriedades. Três parâmetros são usados para especificar uma constante (parâmetro real variam de nomes):
[in] DWORD dwCPlusTypeFlag -O valor de CorElementType enumeração que especifica o tipo do valor padrão.
[void in] const *pValue -um ponteiro para o valor padrão real. Por exemplo, um ponteiro para o byte de 4 DWORD manter 0x0000002A armazenará uma DWORD valor de 42 decimal no metadados. O tipo (especificado em dwCPlusTypeFlag) do padrão o valor está limitado a um primitivo ou uma seqüência de caracteres. Se dwCPlusTypeFlag é ELEMENT_TYPE_CLASS, o valor padrão será null.
[in] ULONG cchValue - O número de Unicode de caracteres na seqüência de bytes para o qual pValue pontos. Isso é necessário apenas se o tipo especificado na dwCPlusTypeFlag, é ELEMENT_TYPE_STRING. Em outros casos, o comprimento é inferido do tipo.
Valores padrão não são automaticamente inseridos no código de inicialização ou em áreas de dados estaticamente inicializados. Eles simplesmente são registrados nos metadados.
Para indicar que não deseja especificar um valor padrão, defina todos os bits de dwCPlusTypeFlag (ou seja, defina o valor -1).
Ponteiros nulos para parâmetros de retorno
Porque os metadados APIs fazer um mínimo de verificação de erros, eles esperam um ponteiro não-nulo para os parâmetros de retorno nas seguintes circunstâncias:
Em Define métodos, um ponteiro nulo não é necessário para o token retornado. Esses métodos criam o item que você deseja definidos e retornou um token para o item. Você pode escolher descartar o token, se for preciso.
Findmétodos sempre retornam o token para o item se ele for encontrado com êxito.
Em Get métodos, você pode passar null nos parâmetros que você não precisa de volta.
Em Set métodos, não há geralmente nenhum valor de retorno. Você pode passar no token para o item a ser atualizado junto com os valores para atualizar e esses métodos executam a atualização.
Valores de parâmetro para ser ignorada.
Vários métodos nos metadados API permitem alterar as propriedades de um item que foi definido anteriormente. O exemplo a seguir usa a IMetaDataEmit::SetFieldProps método para alterar as propriedades de um campo, que foram previamente fornecidas em uma chamada para IMetaDataEmit::DefineField:
HRESULT SetFieldProps(mdFieldDef fd, DWORD dwFieldFlags,
DWORD dwDefType, void const *pValue, ULONG cchValue)
Às vezes, convém alterar dwFieldFlags , mas não pValue (ou vice-versa). Nesse caso, você deve passar um valor de parâmetro para evitar um erro, mesmo se não quiser alterar esse valor. No entanto, você pode passar um valor específico que designa o argumento deve ser ignorado se não desejar alterar seu valor. Os metadados APIs usam as seguintes convenções para indicar que um argumento do método deve ser ignorado:
Se o parâmetro é um tipo de ponteiro, passe um ponteiro nulo.
Se o parâmetro é um tipo de valor (normalmente uma bitmask de sinalizadores), passe um valor de todos os bits definidos (– 1).
Erro retorna
Quase todos os métodos de IMetaDataDispenserEx, IMetaDataEmit, e IMetaDataImport interfaces retornam um valor HRESULT para indicar seu resultado. Isso tem o valor S_OK se a operação foi bem-sucedida. Se a chamada não teve êxito, ele retorna o valor de outro para descrever o motivo por que a operação falhou.
Um padrão geral entre todos os metadados que APIs é que, se o chamador fornece um buffer de seqüência de caracteres é muito pequeno para conter os resultados, as APIs copiar como número de caracteres como irá caber, mas retornar o valor HRESULT de CLDB_S_TRUNCATION em vez de S_OK.
Os chamadores da IMetadata interfaces são compiladores ou ferramentas. É importante que esses chamadores sempre verificar o status de retorno de cada chamada para detectar erros. Nesses casos, as condições de erro refletem um problema por parte do chamador direto (como, por exemplo, um compilador) em vez do usuário (como, por exemplo, um programa aplicativo).
Gerenciamento de memória
O padrão COM genérico é que o chamador libera a memória que o chamador aloca. No entanto, os métodos de metadados operam de forma diferente.
Muitos métodos de metadados retornam [out] ponteiros para os blocos de memória. Se a memória é parte da heap de metadados do módulo e pertencentes a common language runtime (CLR). Portanto, você recebe um ponteiro diretamente para o armazenamento de memória do CLR dos metadados e o seu aplicativo não é necessário liberar a memória.
Suporte a genéricos
No.NET Framework versão 2.0, os metadados APIs foram estendidas significativamente para oferecer suporte a genéricos (às vezes também chamados de "polimorfismo paramétrico"). Os genéricos são um pouco semelhantes a modelos C++. Um exemplo de definição de uma classe genérica em C# pode ser da seguinte maneira:
public class Dictionary<Key, Val> { . . . }
Nesse caso, o Dictionary classe é parametrizada com dois parâmetros genéricos chamados Key e Val. Quando a classe é instanciada, o usuário seleciona os tipos de parâmetros genéricos, como no exemplo a seguir:
Dictionary<string, int> NameToPhone = new Dictionary<string, int>();
Dictionary<int, string> PhoneToName = new Dictionary<int, string>();