Problemas de implementação para provedores ADSI

Para implementar interfaces ADSI, primeiro implemente a interface COM IDirectoryObject. Ao fornecer essa interface como uma camada de sobrecarga mínima, você fornece aos aplicativos cliente o controle necessário para acessar objetos de diretório diretamente do diretório e não por meio do cache ADSI, que otimiza o desempenho da rede. O uso dessa interface também fornecerá a sua própria implementação com mais flexibilidade.

Em segundo lugar, implemente as interfaces ADSI fundamentais, IADs, IADsContainer, IADsCollection e iadsPropertyValue, IADsPropertyEntry, iadsPropertyList interfaces de cache de propriedade. IADsGroup e IADsMembers também são interfaces em demanda frequente pelo software de administração do sistema.

Em terceiro lugar, implemente as interfaces de gerenciamento de esquema se o serviço de diretório tiver um esquema subjacente: IADsClass, IADsProperty, IADsSyntax. Se não houver nenhum esquema subjacente, use essas interfaces para abstrair as classes e as propriedades usadas pelo serviço de diretório. Esquemas podem ser usados para publicar os recursos do serviço de diretório em clientes ADSI.

Coleções

Os componentes do provedor ADSI podem seguir um dos três modelos para armazenar coleções em cache durante a enumeração. A escolha de um modelo de cache determina o comportamento de ADSI quando um objeto em uma coleção é excluído do serviço de diretório subjacente externo ao ADSI.

Os modelos de cache incluem:

  • Coleções armazenadas em cache com antecedência. A coleção de instâncias de objeto é recuperada do serviço de diretório subjacente em sua totalidade quando IADsCollection::get__NewEnum é chamado para criar um novo objeto enumerador. Se o objeto de origem de uma instância de objeto do Active Directory na coleção recuperada for excluído do serviço de diretório subjacente, o cliente não reconhecerá a exclusão até que um IADs::GetInfo ou IADs::SetInfo tente acessar a coleção.
  • Coleções armazenadas em cache incrementalmente. A coleção é recuperada do serviço de diretório subjacente um objeto por vez quando IEnumVARIANT::Next é chamado. IEnumVARIANT::Reset retornará ao início da coleção no cache e IEnumVARIANT::Next retornará objetos armazenados em cache até que o final do cache seja atingido, momento em que novos objetos serão adicionados do repositório subjacente. Quando uma instância de objeto do Active Directory estiver no cache, o cliente não ficará ciente de sua exclusão do serviço de diretório subjacente até que um IADs::GetInfo ou IADs::SetInfo tente acessar o objeto.
  • Coleções não armazenadas em cache. A coleção é recuperada do serviço de diretório subjacente um objeto por vez quando IEnumVARIANT::Next é chamado. IEnumVARIANT::Reset retornará ao início da coleção no repositório subjacente. As operações IEnumVARIANT::Next e IEnumVARIANT::Reset não podem recuperar objetos excluídos, pois os objetos são recuperados sob demanda do serviço de diretório subjacente. Somente o objeto atual é armazenado em cache; se o objeto atual for excluído, o cliente não ficará ciente de sua exclusão do serviço de diretório subjacente até que um IADs::GetInfo ou IADs::SetInfo tente acessar o objeto.

Independentemente do modelo de cache, lembre-se de que a enumeração ADSI retorna interfaces de serviço do Active Directory para o chamador. Para evitar a sobrecarga de obter um novo ponteiro de interface, os aplicativos ADSI devem armazenar em cache os ponteiros de interface retornados para objetos que eles pretendem manipular. Por exemplo, um aplicativo Visual Basic que enumera um contêiner e preenche uma caixa de listagem com nomes pode armazenar em cache os ponteiros de interface associados aos nomes para uso posterior. Essa abordagem fornecerá um desempenho maior do que preencher a caixa de listagem durante a enumeração e obter um novo ponteiro de interface quando o usuário fizer uma seleção.

Sobre as IDs de Expedição

IDispatch é uma interface de Automação definida pelo COM para controladores que não usam interfaces COM diretamente. O acesso a um objeto por meio do IDispatch é chamado de acesso associado ao nome ou de limite tardio, pois ele ocorre em tempo de execução ("tarde") e usa nomes de cadeia de caracteres de propriedades e métodos para resolver referências ("name"). Em tempo de execução, os clientes passam o nome da cadeia de caracteres da propriedade ou método que desejam chamar para o método IDispatch::GetIDsOfNames(). Se a propriedade ou o método existir no objeto, o identificador de expedição (dispID) da função correspondente será recuperado. O dispID é usado para executar a função por meio de IDispatch::Invoke(). Usando IDispatch, propriedades e métodos nas interfaces expostas por um único objeto aparecem como uma lista simples. Como o acesso associado ao nome requer duas chamadas de função, ele é menos eficiente do que usar uma interface COM diretamente. Os clientes são incentivados a usar as interfaces ADSI COM nos objetos quando o desempenho é uma consideração. Controladores avançados de Automação, como Visual Basic 4.0, podem chamar outras interfaces COM, bem como IDispatch, se as interfaces estiverem em conformidade com as restrições de Automação para tipos de dados e passagem de parâmetro.

Os provedores ADSI geram dispIDs dinamicamente para cada objeto do Active Directory. Os dispIDs recuperados por meio de IDispatch::GetIDsOfNames para um determinado objeto são os valores gerados, mas não os valores que estão na IDL do objeto. Os usuários de IDispatch devem chamar GetIDsOfNames para obter dispIDs válidos em tempo de execução.

Informações de tipo e bibliotecas de tipos

O SDK do ADSI fornece uma biblioteca de tipos, Activeds.tlb, que documenta todas as interfaces padrão com suporte do ADSI. Um provedor deve fornecer uma biblioteca de tipos semelhante para todas as interfaces encontradas no Activeds.tlb, além de quaisquer dados de tipo adicionais para as interfaces implementadas no componente do provedor.

Veja a seguir um exemplo de código IDL.

[ object, uuid(IID_IADsXYZ), oleautomation, dual ]
interface IADsXYZ: IDispatch
{
// Read-only properties.
[propget]
HRESULT AReadOnlyProp ([out, retval]BSTR *pbstrAReadOnlyProp);
 
// Read/write properties.
[propget]
HRESULT AReadWriteProp ([out, retval]long *plAReadWriteProp);
[propput]
HRESULT AReadWriteProp ([in]long lAReadWriteProp);
 
// Methods.
HRESULT AMethod ([in]DATE dateInParameter,
[out, retval]BSTR *pbstrReturnValue);
};

Acesso thread-safe

O COM (Component Object Model) descreve os três modelos de threading a seguir. Aplicativos COM indicam qual modelo está em uso ao inicializar a biblioteca COM usando as funções CoInitialize e CoInitializeEx :

  • Threading único. O único modelo threaded pressupõe um único thread de execução em um processo, supondo ainda que as estruturas de dados COM em um processo não precisem de serialização de acesso.
  • Threading de apartamento. Um objeto COM está associado ao thread que o criou. As chamadas para um objeto em outro thread devem ser executadas pelo thread que criou esse objeto. Para fazer isso, o thread de origem invoca um proxy cliente que organiza a chamada de método e a entrega a uma função de stub de servidor no thread de destino por meio da fila de mensagens Win32 associada ao thread de destino.
  • Threading gratuito. Presume-se que os objetos COM sejam thread safe. Vários threads têm acesso permitido a qualquer objeto no processo sem nenhuma serialização imposta.

O ADSI não pressupõe nenhum modelo de threading específico. Os gravadores de componentes de provedor devem assumir o modelo de threading gratuito e garantir a consistência de suas estruturas de dados internas protegendo-as contra threads não seguros, ou seja, descoordenados, atualizações por meio do uso de objetos de sincronização, como seções críticas ou semáforos.

Bloqueio de objeto

O ADSI não impõe nem define um esquema de bloqueio de objetos. Os provedores de namespaces que dão suporte à serialização de acesso usando bloqueio podem expor o esquema de bloqueio subjacente por meio de extensões específicas do provedor para ADSI.

Nomes de propriedade dentro de um esquema

ADSI representa propriedades como objetos de propriedade dentro do contêiner de esquema ADSI. Isso exige que os nomes de propriedades sejam exclusivos em cada contêiner de esquema. O provedor deve garantir que não haja colisões de nome.

Interface primária

Quando um provedor não consegue identificar qual interface deve ser retornada como a interface primária, IID_IADs deve ser retornado. Isso fornece acesso associado ao nome a todas as propriedades de um objeto por meio do IDispatch e dos métodos IADs::Get, IADs::GetEx, IADs::P ut e IADs::P utEx .