Compartir vía


Configuración y extensión del tiempo de ejecución con comportamientos

Los comportamientos pueden usarse para modificar el comportamiento predeterminado y agregar extensiones personalizadas con las que inspeccionar y validar la configuración de un servicio o modificar el comportamiento en tiempo de ejecución de las aplicaciones de cliente y servicio de Windows Communication Foundation (WCF). En este tema se describen las interfaces de comportamiento, cómo implementarlas y cómo agregarlas mediante programación a la descripción del servicio (en una aplicación de servicio) o punto de conexión (en una aplicación cliente) o en un archivo de configuración. Para obtener más información sobre el uso de comportamientos proporcionados por el sistema, consulte Especificación del comportamiento en tiempo de ejecución del servicio y Especificación del comportamiento de tiempo de ejecución del cliente.

Comportamientos

Los tipos de comportamiento deben agregarse al servicio o a los objetos de descripción de puntos de conexión de servicio (en el servicio o en el cliente, respectivamente) antes de que se usen en Windows Communication Foundation (WCF) para crear un tiempo de ejecución donde se ejecute un servicio o un cliente de WCF. Cuando se llama a estos comportamientos durante el proceso de construcción en tiempo de ejecución, podrá tener acceso a las propiedades y métodos en tiempo de ejecución que modifican el tiempo de ejecución construido por el contrato, enlaces y direcciones.

Métodos de comportamiento

Todo los comportamientos tienen un método AddBindingParameters, un método ApplyDispatchBehavior, un método Validate y un método ApplyClientBehavior con una excepción: como IServiceBehavior no puede ejecutarse en un cliente, no implementará ApplyClientBehavior.

  • Utilice el método AddBindingParameters para modificar o agregar los objetos personalizados a una colección a la que los enlaces personalizados pueden tener acceso para su uso cuando se construya el tiempo de ejecución. Por ejemplo, la forma en que se especifican los requisitos de protección que afectan a la manera en que se crea el canal pero no es conocido por el desarrollador de canales.

  • Utilice el método Validate para examinar el árbol de descripción y el objeto del tiempo de ejecución correspondiente para garantizar que se ajusta a algún conjunto de criterios.

  • Utilice los métodos ApplyDispatchBehavior y ApplyClientBehavior para examinar el árbol de descripción y modificar el tiempo de ejecución para un ámbito determinado en el servicio o el cliente. También puede insertar los objetos de extensión.

    Nota

    Aunque se proporciona un árbol de descripción en estos métodos, solo es para el examen. Si se modifica un árbol de descripción, el comportamiento es indefinido.

Se tiene acceso a las propiedades que puede modificar y las interfaces de personalización que puede implementar a través de las clases de tiempo de ejecución de servicio y de cliente. Los tipos de servicio son las clases DispatchRuntime y DispatchOperation. Los tipos de cliente con las clases ClientRuntime y ClientOperation. Las clases ClientRuntime y DispatchRuntime son los puntos de entrada de la extensibilidad para tener acceso a las propiedades en tiempo de ejecución del cliente y del servicio y las colecciones de extensión, respectivamente. De forma similar, en las clases ClientOperation y DispatchOperation se exponen las propiedades en tiempo de ejecución de la operación de cliente y de la operación de servicio, así como las colecciones de extensiones, respectivamente. Puede, sin embargo, tener acceso al objeto en tiempo de ejecución de un ámbito más amplio a partir del objeto de tiempo de ejecución de la operación y viceversa, si fuera necesario.

Nota

Para obtener una explicación sobre las propiedades en tiempo de ejecución y los tipos de extensión que pueden usarse para modificar el comportamiento de ejecución de un cliente, consulte Extensión de clientes. Para obtener una explicación sobre las propiedades en tiempo de ejecución y los tipos de extensión que pueden usarse para modificar el comportamiento de ejecución de un distribuidor de servicios, consulte Extensión de distribuidores.

La mayoría de los usuarios de WCF no interactúan directamente con el tiempo de ejecución; en su lugar, se usan las construcciones básicas del modelo de programación (como los puntos de conexión, los contratos, los enlaces, las direcciones y los atributos de comportamiento) en clases o en comportamientos mediante archivos de configuración. Estas construcciones constituyen el árbol de descripción, que es la especificación completa para la construcción de un tiempo de ejecución donde se admita el uso de un servicio o del cliente que se describe en el árbol de descripción.

En WCF, se incluyen los cuatro tipos de comportamientos siguientes:

Puede agregar estos comportamientos a los distintos objetos de descripción implementando los atributos personalizados, utilizando los archivos de configuración de la aplicación, o directamente agregándolos a la colección de comportamientos en el objeto de descripción adecuado. Sin embargo, deben agregarse a la descripción del servicio o a un objeto de descripción del punto de conexión del servicio antes de llamar a ICommunicationObject.Open en ServiceHost o ChannelFactory<TChannel>.

Ámbitos de comportamiento

Hay cuatro tipos de comportamiento, cada uno de los cuales se corresponde con un ámbito determinado de acceso en tiempo de ejecución.

Comportamientos de servicio

Los comportamientos de servicio, que implementan IServiceBehavior, son el mecanismo principal por medio del cual modifica el tiempo de ejecución del servicio completo. Hay tres mecanismos para agregar los comportamientos de servicio a un servicio.

  1. Utilizar un atributo en la clase de servicio. Cuando se construye un ServiceHost, la implementación de ServiceHost utiliza la reflexión para detectar el conjunto de atributos en el tipo del servicio. Si cualquiera de estos atributos es una implementación de IServiceBehavior, se agregan a la colección de comportamientos en ServiceDescription. Esto permite a esos comportamientos participar en la construcción del tiempo de ejecución del servicio.

  2. Agregar mediante programación el comportamiento a la colección de comportamientos en ServiceDescription. Esto se puede lograr con las siguientes líneas de código:

    ServiceHost host = new ServiceHost(/* Parameters */);  
    host.Description.Behaviors.Add(/* Service Behavior */);  
    
  3. Implementar un BehaviorExtensionElement personalizado que extiende la configuración. Esto permite el uso del comportamiento de servicio a partir de los archivos de configuración de la aplicación.

Entre los comportamientos de servicio de WCF se incluyen la clase de atributo ServiceBehaviorAttribute y las clases de comportamiento ServiceThrottlingBehavior y ServiceMetadataBehavior.

Comportamientos de contrato

Los comportamientos de contrato, que implementan la interfaz IContractBehavior, se utilizan para extender el tiempo de ejecución del cliente y el servicio en un contrato.

Hay dos mecanismos para agregar los comportamientos del contrato a un contrato. El primer mecanismo es crear un atributo personalizado que se va a utilizar en la interfaz de contrato. Cuando una interfaz de contrato se pasa a una clase ServiceHost o ChannelFactory<TChannel>, los atributos de la interfaz se examinan en el motor WCF. Si los atributos son implementaciones de IContractBehavior, se agregarán a la colección de comportamientos en el System.ServiceModel.Description.ContractDescription creado para esa interfaz.

También puede implementar System.ServiceModel.Description.IContractBehaviorAttribute en el atributo de comportamiento de contrato personalizado. En este caso, el comportamiento es como sigue cuando se aplica a:

•Una interfaz de contrato. En este caso, el comportamiento se aplicará a todos los contratos de ese tipo en cualquier punto de conexión y, además, el valor de la propiedad IContractBehaviorAttribute.TargetContract se omitirá en el motor WCF.

•Una clase de servicio. En este caso, el comportamiento se aplica solo a los puntos de conexión cuyo contrato es el valor de la propiedad TargetContract.

•Una clase de devolución de llamada. En este caso, el comportamiento se aplicará al punto de conexión del cliente dúplex y el valor de la propiedad TargetContract se omitirá en el motor WCF.

El segundo mecanismo es agregar el comportamiento a la colección de comportamientos en ContractDescription.

Entre los comportamientos de contrato de WCF, se incluye el atributo System.ServiceModel.DeliveryRequirementsAttribute. Para obtener más información y un ejemplo, vea el tema de referencia.

Comportamientos del extremo

Los comportamientos del punto de conexión, que implementan IEndpointBehavior, son el mecanismo principal por medio del cual modifica todo el servicio o el tiempo de ejecución del cliente para un punto de conexión concreto.

Hay dos mecanismos para agregar los comportamientos del extremo a un servicio.

  1. Agregue el comportamiento a la propiedad Behaviors.

  2. Implementar un BehaviorExtensionElement personalizado que extiende la configuración.

Para obtener más información y un ejemplo, vea el tema de referencia.

Comportamientos de la operación

Los comportamientos de la operación, que implementan la interfaz IOperationBehavior, se utilizan para extender el tiempo de ejecución del cliente y el servicio para cada operación.

Hay dos mecanismos para agregar los comportamientos de la operación a una operación. El primero es crear un atributo personalizado que se va a utilizar en el método que modela la operación. Cuando una operación se agrega a una clase ServiceHost o ChannelFactory, cualquier atributo de la interfaz IOperationBehavior se agregará a, desde WCF, a la colección de comportamientos en la instancia de la clase OperationDescription que se haya creado para esa operación.

El segundo mecanismo es agregar directamente el comportamiento a la colección de comportamientos en un OperationDescriptionconstruido.

Entre los comportamientos de operación de WCF, se incluyen las clases de atributo OperationBehaviorAttribute y TransactionFlowAttribute.

Para obtener más información y un ejemplo, vea el tema de referencia.

Uso de la configuración para crear comportamientos

Los comportamientos de servicio y extremo, y contrato pueden diseñarse para que se especifiquen en el código o utilicen atributos; solo se pueden configurar los comportamientos de servicio y extremo mediante la aplicación o los archivos de configuración web. Los desarrolladores pueden exponer comportamientos mediante atributos para especificar un comportamiento en el momento de la compilación que no pueda agregarse, eliminarse ni modificarse en el tiempo de ejecución. Esto es a menudo conveniente para los comportamientos que siempre se necesitan para la operación correcta de un servicio (por ejemplo, los parámetros relacionados con la transacción al atributo System.ServiceModel.ServiceBehaviorAttribute). Exponer comportamientos que utilizan la configuración permite a los desarrolladores dejar la especificación y la configuración de dichos comportamientos a los que implementan el servicio. Esto es conveniente para los comportamientos que son componentes opcionales u otra configuración específica de la implementación, por ejemplo, si los metadatos se exponen para el servicio o la configuración de autorización determinada para un servicio.

Nota

También puede utilizar comportamientos que admiten la configuración para exigir las directivas de aplicación de la empresa insertándolas en el archivo de configuración machine.config y bloqueando esos elementos. Para obtener una descripción y un ejemplo, consulte Procedimiento para bloquear puntos de conexión en la empresa.

Para exponer un comportamiento mediante la configuración, un desarrollador debe crear una clase derivada de BehaviorExtensionElement y, a continuación, registrar esa extensión con la configuración.

En el siguiente ejemplo de código, se muestra cómo una instancia de la interfaz IEndpointBehavior implementa la clase BehaviorExtensionElement:

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

Para que el sistema de configuración cargue un BehaviorExtensionElement personalizado, se debe registrar como una extensión. El ejemplo de código siguiente muestra el archivo de configuración para el comportamiento del extremo 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>  

En este código, el elemento Microsoft.WCF.Documentation.EndpointBehaviorMessageInspector se usa para representar el tipo de extensión de comportamiento y el elemento HostApplication debe corresponderse con el nombre del ensamblado en el que se ha compilado esa clase.

Orden de evaluación

System.ServiceModel.ChannelFactory<TChannel> y System.ServiceModel.ServiceHost son responsables de generar el tiempo de ejecución del modelo de programación y descripción. Los comportamientos, tal y como se han descritos previamente, contribuyen a ese proceso de creación en el servicio, punto de conexión, contrato y operación.

ServiceHost aplica los comportamientos en el orden siguiente:

  1. Servicio

  2. Contrato

  3. punto de conexión

  4. Operación

Dentro de cualquier colección de comportamientos, no se garantiza ningún orden.

ChannelFactory<TChannel> aplica los comportamientos en el orden siguiente:

  1. Contrato

  2. punto de conexión

  3. Operación

De nuevo, dentro de cualquier colección de comportamientos, no se garantiza ningún orden.

Adición de comportamientos mediante programación

Las propiedades de System.ServiceModel.Description.ServiceDescription en la aplicación de servicio no se deben modificar después del método CommunicationObject.OnOpening en System.ServiceModel.ServiceHostBase. Algunos miembros, como la propiedad ServiceHostBase.Credentials y los métodos AddServiceEndpoint en ServiceHostBase y System.ServiceModel.ServiceHost, producen una excepción si se modificas pasados ese punto. Otros permiten modificarlos, pero el resultado no está definido.

De igual forma, en el cliente no se deben modificar los valores System.ServiceModel.Description.ServiceEndpoint después de la llamada a OnOpening en System.ServiceModel.ChannelFactory. La propiedad ChannelFactory.Credentials produce una excepción si se modifica pasado ese punto, pero los otros valores de descripción del cliente se pueden modificar sin el error. El resultado, sin embargo, es indefinido.

Tanto si es para el servicio como para el cliente, se recomienda modificar la descripción antes de llamar a CommunicationObject.Open.

La herencia gobierna para los atributos de comportamiento

Los cuatro tipos de comportamientos se pueden rellenar utilizando los atributos: los comportamientos de servicio y de contrato. Debido a que los atributos se definen en los objetos y miembros administrados y estos admiten la herencia, será necesario definir cómo funcionan los atributos en el contexto de la herencia.

En un nivel alto, la regla es que para un ámbito determinado (por ejemplo, servicio, contrato u operación) se aplican todos los atributos de comportamiento en la jerarquía de la herencia para ese ámbito. Si hay dos atributos de comportamiento del mismo tipo, solo se utiliza el tipo más derivado.

Comportamientos de servicio

Para una clase de servicio determinada, se aplicarán todos los atributos de comportamiento del servicio en esa clase y en los elementos primarios de esa clase. Si el mismo tipo de atributo se aplica en varios lugares en la jerarquía de la herencia, se usará el tipo más derivado.

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

Por ejemplo, en el caso anterior, el servicio B finaliza con un InstanceContextMode de Single, un modo AspNetCompatibilityRequirementsMode de Allowed y un ConcurrencyMode de Single. ConcurrencyMode es Single, porque el atributo ServiceBehaviorAttribute en el servicio B está "más derivado" que en el servicio A.

Comportamientos de contrato

Para un contrato determinado, se aplicarán todos los atributos de comportamiento de contrato en esa interfaz y en los elementos primarios de esa interfaz. Si el mismo tipo de atributo se aplica en varios lugares en la jerarquía de la herencia, se usará el tipo más derivado.

Comportamientos de la operación

Si una operación determinada no invalida ningún resumen existente ni la operación virtual, no se aplicará ninguna regla de herencia.

Si una operación invalida una operación existente, se aplicarán todos los atributos de comportamiento de operación en esa operación y en los elementos primarios de esa operación. Si el mismo tipo de atributo se aplica en varios lugares en la jerarquía de la herencia, se usará el tipo más derivado.