2012-04-19 12 views
7

Tengo una extensión de comportamiento WCF que me gustaría agregar a un cliente WCF. Sin embargo, el cliente se construye programáticamente. La dirección del punto final puede variar, pero sé el tipo. Podría agregar el comportamiento programáticamente o en el archivo de configuración (preferido), pero necesito pasar alguna configuración en el archivo de configuración solamente.Configurar declaradamente la extensión de comportamiento WCF en el punto final construido mediante programación

No quiero esto en Comportamientos comunes (machine.config).

puedo añadir el comportamiento mediante programación

endpoint.Behaviors.Add(new MyCustomBehavior()) 

pero prefiero hacerlo en la configuración, por lo que puede configurar la extensión allí también.

¿Es posible agregar y configurar de forma declarativa una extensión de comportamiento de punto final a un punto final construido mediante programación sabiendo únicamente que el tipo o interfaz mientras se deja el punto final del cliente se construirá mediante programación?

<system.serviceModel> 
    <client> 
    <!-- Created programmatically --> 
    </client> 
<extensions> 
    <behaviorExtensions> 
    <add name="MyCustomBehavior" type="namespace.CustomBehaviors", MyAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
    </behaviorExtensions> 
</extensions> 
    <behaviors> 
    <endpointBehaviors> 
     <behavior name="MyCustomBehavior"> 
     <MyCustomBehavior MyImportantBehaviorParam1="foo" /> 
     </behavior> 
    </endpointBehaviors> 
    </behaviors> 
</system.serviceModel> 

Por supuesto que podría poner la configuración en otra sección, y tienen mi comportamiento leer ahí, pero yo prefiero utilizar las instalaciones de WCF, si es posible.

Respuesta

10

Para hacer eso, necesita crear una extensión de configuración de comportamiento para su punto final. Para obtener más información sobre cómo hacerlo, verifique http://blogs.msdn.com/b/carlosfigueira/archive/2011/06/28/wcf-extensibility-behavior-configuration-extensions.aspx.

Actualización: Veo su problema ahora. No hay forma directa de agregar a un punto final creado a través de un código un comportamiento declarado en la configuración. Sin embargo, aún puede hacerlo, pero deberá usar algún reflejo para acceder al método CreateBehavior de la extensión de configuración de comportamiento (el método está protegido) para crear realmente el comportamiento del punto final y agregarlo al punto final creado mediante el código. El siguiente código muestra cómo se puede hacer esto.

public class StackOverflow_10232385 
{ 
    public class MyCustomBehavior : IEndpointBehavior 
    { 
     public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 
     { 
      Console.WriteLine("In {0}.{1}", this.GetType().Name, MethodBase.GetCurrentMethod().Name); 
     } 

     public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) 
     { 
      Console.WriteLine("In {0}.{1}", this.GetType().Name, MethodBase.GetCurrentMethod().Name); 
     } 

     public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) 
     { 
      Console.WriteLine("In {0}.{1}", this.GetType().Name, MethodBase.GetCurrentMethod().Name); 
     } 

     public void Validate(ServiceEndpoint endpoint) 
     { 
      Console.WriteLine("In {0}.{1}", this.GetType().Name, MethodBase.GetCurrentMethod().Name); 
     } 
    } 

    public class MyCustomBehaviorExtension : BehaviorExtensionElement 
    { 
     public override Type BehaviorType 
     { 
      get { return typeof(MyCustomBehavior); } 
     } 

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

    [ServiceContract] 
    public interface ITest 
    { 
     [OperationContract] 
     string Echo(string text); 
    } 
    public class Service : ITest 
    { 
     public string Echo(string text) 
     { 
      return text; 
     } 
    } 

    public static void Test() 
    { 
     string baseAddress = "http://" + Environment.MachineName + ":8000/Service"; 
     ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress)); 
     ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), ""); 

     var configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 
     ServiceModelSectionGroup smsg = configuration.GetSectionGroup("system.serviceModel") as ServiceModelSectionGroup; 
     EndpointBehaviorElement endpointBehaviorElement = smsg.Behaviors.EndpointBehaviors["MyCustomBehavior_10232385"]; 
     foreach (BehaviorExtensionElement behaviorElement in endpointBehaviorElement) 
     { 
      MethodInfo createBehaviorMethod = behaviorElement.GetType().GetMethod("CreateBehavior", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Type.EmptyTypes, null); 
      IEndpointBehavior behavior = createBehaviorMethod.Invoke(behaviorElement, new object[0]) as IEndpointBehavior; 
      endpoint.Behaviors.Add(behavior); 
     } 

     host.Open(); 
     Console.WriteLine("Host opened"); 

     ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress)); 
     ITest proxy = factory.CreateChannel(); 
     Console.WriteLine(proxy.Echo("Hello")); 

     ((IClientChannel)proxy).Close(); 
     factory.Close(); 

     Console.Write("Press ENTER to close the host"); 
     Console.ReadLine(); 
     host.Close(); 
    } 
} 

Y la configuración de este código:

<system.serviceModel> 
    <extensions> 
     <behaviorExtensions> 
      <add name="myCustomBehavior_10232385" type="QuickCode1.StackOverflow_10232385+MyCustomBehaviorExtension, QuickCode1"/> 
     </behaviorExtensions> 
    </extensions> 
    <behaviors> 
     <endpointBehaviors> 
      <behavior name="MyCustomBehavior_10232385"> 
       <myCustomBehavior_10232385/> 
      </behavior> 
     </endpointBehaviors> 
    </behaviors> 
</system.serviceModel> 
+0

Mi comportamiento ya implementa la extensión del comportamiento, tenga en cuenta el parámetro en ... Lo siento si mi pregunta no era clara, pero en toda la ejemplos que puedo encontrar, el behaviorConfiguration se agrega a un punto final construido declarativamente (servicio o cliente). Necesito saber cómo agregarlo a los puntos finales con un contrato determinado que se crean mediante programación. – DanO

+0

Entendido, no lo entendí antes. He actualizado la respuesta con esto y puedes encontrar el código completo en https://github.com/carlosfigueira/WCFQuickSamples/tree/master/WCFForums/QuickCode1. – carlosfigueira

+0

¡Gracias por el esfuerzo realizado para proporcionar esa solución! Ya dejé de hacer lo que quería a favor de lo que era más fácil, pero si vuelvo a visitar ese proyecto, ¡su código será de gran ayuda! – DanO

Cuestiones relacionadas