Compartilhar via


Configurando e estendendo o runtime com comportamentos

Os comportamentos permitem modificar o comportamento padrão e adicionar extensões personalizadas que inspecionam e validam a configuração de serviço ou modificam o comportamento de runtime em aplicativos de cliente e serviço do WCF (Windows Communication Foundation). Este tópico descreve as interfaces de comportamento, como implementá-las e como adicioná-las à descrição do serviço (em um aplicativo de serviço) ou ponto de extremidade (em um aplicativo cliente) programaticamente ou em um arquivo de configuração. Para obter mais informações sobre como usar comportamentos fornecidos pelo sistema, consulte Especificando o comportamento do Run-Time de serviço e especificando o comportamento do cliente Run-Time.

Comportamentos

Os tipos de comportamento são adicionados aos objetos de descrição do serviço ou do ponto de extremidade de serviço (no serviço ou no cliente, respectivamente) antes que esses objetos sejam usados pelo WCF (Windows Communication Foundation) para criar um runtime que executa um serviço WCF ou um cliente WCF. Quando esses comportamentos são chamados durante o processo de construção do runtime, eles são capazes de acessar propriedades e métodos de runtime que modificam o runtime construído pelo contrato, associações e endereços.

Métodos de comportamento

Todos os comportamentos têm um AddBindingParameters método, um ApplyDispatchBehavior método, um Validate método e um ApplyClientBehavior método com uma exceção: como IServiceBehavior não é possível executar em um cliente, ele não implementa ApplyClientBehavior.

  • Use o método AddBindingParameters para modificar ou adicionar objetos personalizados a uma coleção que as associações personalizadas podem acessar para seu uso quando o runtime for construído. Por exemplo, é assim que os requisitos de proteção são especificados que afetam a forma como o canal é criado, mas não são conhecidos pelo desenvolvedor do canal.

  • Use o Validate método para examinar a árvore de descrição e o objeto de runtime correspondente para garantir que ele esteja em conformidade com algum conjunto de critérios.

  • Use os métodos ApplyDispatchBehavior e ApplyClientBehavior para examinar a árvore de descrição e modificar o tempo de execução para um escopo específico, seja no serviço ou no cliente. Você também pode inserir objetos de extensão.

    Observação

    Embora uma árvore de descrição seja fornecida nesses métodos, ela é apenas para exame. Se uma árvore de descrição for modificada, o comportamento será indefinido.

As propriedades que você pode modificar e as interfaces de personalização que você pode implementar são acessadas por meio das classes de runtime de serviço e cliente. Os tipos de serviço são as classes DispatchRuntime e DispatchOperation. Os tipos de cliente são as classes ClientRuntime e ClientOperation. As classes ClientRuntime e DispatchRuntime são os pontos de entrada para a extensibilidade, permitindo o acesso às propriedades de tempo de execução e às coleções de extensões, tanto para o cliente como para o serviço, respectivamente. Da mesma forma, as classes ClientOperation e DispatchOperation expõem as propriedades de runtime de operação e de serviço do cliente e as coleções de extensões, respectivamente. No entanto, você pode acessar o objeto runtime com escopo mais amplo do objeto runtime da operação e vice-versa, se necessário.

Observação

Para uma discussão sobre propriedades de runtime e tipos de extensão que você pode usar para modificar o comportamento de execução de um cliente, consulte Estendendo clientes. Para uma discussão sobre propriedades de runtime e tipos de extensão que você pode usar para modificar o comportamento de execução de um dispatcher de serviço, consulte Extending Dispatchers.

A maioria dos usuários do WCF não interage diretamente com o runtime; Em vez disso, eles usam constructos de modelo de programação principais, como pontos de extremidade, contratos, associações, endereços e atributos de comportamento em classes ou comportamentos em arquivos de configuração. Esses constructos compõem a árvore de descrição, que é a especificação completa para construir um runtime para dar suporte a um serviço ou cliente descrito pela árvore de descrição.

Há quatro tipos de comportamentos no WCF:

Você pode adicionar esses comportamentos aos vários objetos de descrição implementando atributos personalizados, usando arquivos de configuração de aplicativo ou diretamente adicionando-os à coleção de comportamentos no objeto de descrição apropriado. No entanto, deve ser adicionado a um objeto de descrição do ponto de extremidade de serviço ou descrição do ponto de extremidade de serviço antes de chamar ICommunicationObject.Open em ServiceHost ou ChannelFactory<TChannel>.

Escopos de comportamento

Há quatro tipos de comportamento, cada um deles corresponde a um escopo específico de acesso de runtime.

Comportamentos de serviço

Os comportamentos de serviço, que implementam IServiceBehavior, são o mecanismo primário pelo qual você modifica todo o runtime do serviço. Há três mecanismos para adicionar comportamentos de serviço a um serviço.

  1. Usando um atributo na classe de serviço. Quando um ServiceHost é construído, a ServiceHost implementação usa reflexão para descobrir o conjunto de atributos no tipo do serviço. Se qualquer um desses atributos for implementações de IServiceBehavior, eles serão adicionados à coleção de comportamentos em ServiceDescription. Isso permite que esses comportamentos participem da construção do runtime do serviço.

  2. Adicionando programaticamente o comportamento à coleção de comportamentos em ServiceDescription. Isso pode ser feito com as seguintes linhas de código:

    ServiceHost host = new ServiceHost(/* Parameters */);
    host.Description.Behaviors.Add(/* Service Behavior */);
    
  3. Implemente um BehaviorExtensionElement personalizado que estenda a configuração. Isso permite a aplicação do comportamento de serviço a partir dos arquivos de configuração do aplicativo.

Exemplos de comportamentos de serviço no WCF incluem o comportamento ServiceBehaviorAttribute, o comportamento ServiceThrottlingBehavior e o comportamento ServiceMetadataBehavior.

Comportamentos de contrato

Os comportamentos de contrato, que implementam a IContractBehavior interface, são usados para estender o tempo de execução do cliente e do serviço ao longo de um contrato.

Há dois mecanismos para adicionar comportamentos de contrato a um contrato. O primeiro mecanismo é criar um atributo personalizado a ser usado na interface do contrato. Quando uma interface de contrato é passada para um ServiceHost ou um ChannelFactory<TChannel>, o WCF examina os atributos da interface. Se quaisquer atributos forem implementações de IContractBehavior, aqueles serão adicionados à coleção de comportamentos na interface System.ServiceModel.Description.ContractDescription criada especificamente para essa finalidade.

Você também pode implementar o atributo System.ServiceModel.Description.IContractBehaviorAttribute de comportamento do contrato personalizado. Nesse caso, o comportamento é o seguinte quando aplicado a:

• Uma interface de contrato. Nesse caso, o comportamento é aplicado a todos os contratos desse tipo em qualquer endpoint, e o WCF ignora o valor da propriedade IContractBehaviorAttribute.TargetContract.

•Uma classe de serviço. Nesse caso, o comportamento é aplicado somente aos pontos de extremidade do contrato do qual é o valor da propriedade TargetContract.

• Uma classe de retorno de chamada. Nesse caso, o comportamento é aplicado ao endpoint do cliente duplex e o WCF ignora o valor da propriedade TargetContract.

O segundo mecanismo é adicionar o comportamento à coleção de comportamentos em um ContractDescription.

Exemplos de comportamentos de contrato no WCF incluem o atributo System.ServiceModel.DeliveryRequirementsAttribute. Para obter mais informações e um exemplo, consulte o tópico de referência.

Comportamentos de Ponto de Extremidade

Os comportamentos de ponto de extremidade, que implementam IEndpointBehavior, são o mecanismo primário pelo qual você modifica todo o serviço ou o tempo de execução do cliente para um ponto de extremidade específico.

Há dois mecanismos para adicionar comportamentos de ponto de extremidade a um serviço.

  1. Adicione o comportamento à propriedade Behaviors.

  2. Implemente um BehaviorExtensionElement personalizado que amplie a configuração.

Para obter mais informações e um exemplo, consulte o tópico de referência.

Comportamentos de operação

Os comportamentos de operação, que implementam a IOperationBehavior interface, são usados para estender o runtime do cliente e do serviço para cada operação.

Há dois mecanismos para adicionar comportamentos de operação a uma operação. O primeiro mecanismo é criar um atributo personalizado a ser usado no método que modela a operação. Quando uma operação é adicionada a um ServiceHost ou a um ChannelFactory, o WCF adiciona quaisquer atributos de IOperationBehavior à coleção de comportamentos no OperationDescription criado especificamente para aquela operação.

O segundo mecanismo é adicionar diretamente o comportamento à coleção de comportamentos em um constructo OperationDescription.

Exemplos de comportamentos de operação no WCF incluem o OperationBehaviorAttribute e o TransactionFlowAttribute.

Para obter mais informações e um exemplo, consulte o tópico de referência.

Usando a configuração para criar comportamentos

Comportamentos de serviço e ponto de extremidade e contrato podem ser projetados para serem especificados no código ou usando atributos; somente os comportamentos de serviço e ponto de extremidade podem ser configurados usando arquivos de configuração do aplicativo ou da Web. Expor comportamentos usando atributos permite que os desenvolvedores especifiquem um comportamento em tempo de compilação que não pode ser adicionado, removido ou modificado no runtime. Isso geralmente é adequado para comportamentos que são sempre necessários para a operação correta de um serviço (por exemplo, os parâmetros relacionados à transação ao System.ServiceModel.ServiceBehaviorAttribute atributo). Expor comportamentos usando a configuração permite que os desenvolvedores deixem a especificação e a configuração desses comportamentos para aqueles que implantam o serviço. Isso é adequado para comportamentos que são componentes opcionais ou outra configuração específica de implantação, como se os metadados são expostos para o serviço ou a configuração de autorização específica para um serviço.

Observação

Você também pode usar comportamentos que dão suporte à configuração para impor políticas de aplicativo da empresa inserindo-as no arquivo de configuração machine.config e bloqueando esses itens. Para obter uma descrição e um exemplo, consulte Como bloquear pontos de extremidade na empresa.

Para expor um comportamento usando a configuração, um desenvolvedor deve criar uma classe BehaviorExtensionElement derivada e, em seguida, registrar essa extensão com a configuração.

O exemplo de código a seguir mostra como um IEndpointBehavior implementa BehaviorExtensionElement:

// BehaviorExtensionElement members
public override Type BehaviorType
{
  get { return typeof(EndpointBehaviorMessageInspector); }
}

protected override object CreateBehavior()
{
  return new EndpointBehaviorMessageInspector();
}

Para que o sistema de configuração carregue um componente personalizado BehaviorExtensionElement, ele deve ser registrado como uma extensão. O exemplo de código a seguir mostra o arquivo de configuração para o comportamento do ponto de extremidade anterior:

<configuration>
  <system.serviceModel>
    <services>
      <service
        name="Microsoft.WCF.Documentation.SampleService"
        behaviorConfiguration="metadataSupport"
      >
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8080/ServiceMetadata" />
          </baseAddresses>
        </host>
        <endpoint
          address="/SampleService"
          binding="wsHttpBinding"
          behaviorConfiguration="withMessageInspector"
          contract="Microsoft.WCF.Documentation.ISampleService"
        />
        <endpoint
           address="mex"
           binding="mexHttpBinding"
           contract="IMetadataExchange"
        />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
      <behavior name="metadataSupport">
        <serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
      </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="withMessageInspector">
          <endpointMessageInspector />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <extensions>
      <behaviorExtensions>
        <add
          name="endpointMessageInspector"
          type="Microsoft.WCF.Documentation.EndpointBehaviorMessageInspector, HostApplication, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
        />
      </behaviorExtensions>
    </extensions>
  </system.serviceModel>
</configuration>

Onde Microsoft.WCF.Documentation.EndpointBehaviorMessageInspector está o tipo de extensão de comportamento e HostApplication é o nome do assembly no qual essa classe foi compilada.

Ordem de Avaliação

O System.ServiceModel.ChannelFactory<TChannel> e o System.ServiceModel.ServiceHost são responsáveis pela construção do runtime a partir do modelo de programação e da descrição. Os comportamentos, conforme descrito anteriormente, contribuem para esse processo de build no serviço, ponto de extremidade, contrato e operação.

A ServiceHost aplica comportamentos na seguinte ordem:

  1. Serviço

  2. Contrato

  3. Ponto final

  4. Operação

Em qualquer coleção de comportamentos, nenhuma ordem é garantida.

A ChannelFactory<TChannel> aplica comportamentos na seguinte ordem:

  1. Contrato

  2. Ponto final

  3. Operação

Dentro de qualquer coleção de comportamentos, novamente, nenhuma ordem é garantida.

Adicionando comportamentos programaticamente

As propriedades do System.ServiceModel.Description.ServiceDescription na aplicação de serviço não devem ser modificadas após o método CommunicationObject.OnOpening em System.ServiceModel.ServiceHostBase. Alguns membros, como a propriedade ServiceHostBase.Credentials e os métodos AddServiceEndpoint em ServiceHostBase e System.ServiceModel.ServiceHost, lançam uma exceção se modificados além desse ponto. Outros permitem modificá-los, mas o resultado é indefinido.

Da mesma forma, os valores de System.ServiceModel.Description.ServiceEndpoint no cliente não devem ser modificados após a chamada para OnOpening no System.ServiceModel.ChannelFactory. A ChannelFactory.Credentials propriedade gera uma exceção se modificada após esse ponto, mas os outros valores de descrição do cliente podem ser modificados sem erros. O resultado, no entanto, é indefinido.

Seja para o serviço ou cliente, é recomendável modificar a descrição antes de chamar CommunicationObject.Open.

Regras de herança para atributos de comportamento

Todos os quatro tipos de comportamentos podem ser preenchidos usando atributos – comportamentos de serviço e comportamentos de contrato. Como os atributos são definidos em objetos e membros gerenciados e os objetos gerenciados e os membros dão suporte à herança, é necessário definir como os atributos de comportamento funcionam no contexto da herança.

Em um alto nível, a regra é que, para um escopo específico (por exemplo, serviço, contrato ou operação), todos os atributos de comportamento na hierarquia de herança para esse escopo são aplicados. Se houver dois atributos de comportamento do mesmo tipo, somente o tipo mais derivado será usado.

Comportamentos de serviço

Para uma determinada classe de serviço, todos os atributos de comportamento de serviço são aplicados nessa classe e nos pais dessa classe. Se o mesmo tipo de atributo for aplicado em vários locais na hierarquia de herança, o tipo mais derivado será usado.

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
[AspNetCompatibilityRequirementsAttribute(
    AspNetCompatibilityRequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class A { /* … */ }

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class B : A { /* … */}

Por exemplo, no caso anterior, o serviço B acaba com um InstanceContextMode de Single, um modo AspNetCompatibilityRequirementsMode de Allowed, e um ConcurrencyMode de Single. O ConcurrencyMode é Single, porque o atributo ServiceBehaviorAttribute no serviço B está em "mais derivado" do que no serviço A.

Comportamentos de contrato

Para um determinado contrato, todos os atributos de comportamento do contrato nessa interface e nos pais dessa interface são aplicados. Se o mesmo tipo de atributo for aplicado em vários locais na hierarquia de herança, o tipo mais derivado será usado.

Comportamentos de operação

Se uma determinada operação não substituir uma operação abstrata ou virtual existente, nenhuma regra de herança será aplicada.

Se uma operação substituir uma operação existente, todos os atributos de comportamento dessa operação e de suas operações-mãe serão aplicados. Se o mesmo tipo de atributo for aplicado em vários locais na hierarquia de herança, o tipo mais derivado será usado.