2014-11-19 4 views
2

Я использую следующий [TrackingBehaviorAttribute] вместе с пользовательским IOperationInvoker на некоторых [OperationContract], и все в порядке.Использование атрибута (IOperationBehavior) для всех методов обслуживания

Но я ищу способ добавить этот атрибут на уровне интерфейса (уровень [ServiceContract]). Я хочу избежать ручного процесса добавления атрибута для каждого метода внутри службы.

using System.Reflection; 
using System.ServiceModel; 
using System.ServiceModel.Description; 
using System.ServiceModel.Dispatcher; 
using System.ServiceModel.Channels;  

public class TrackingBehaviorAttribute : Attribute, IOperationBehavior 
    { 
     #region IOperationBehavior Members 
     public void AddBindingParameters(OperationDescription operationDescription, 
             BindingParameterCollection bindingParameters) 
     { 
     } 

     public void ApplyClientBehavior(OperationDescription operationDescription, 
             ClientOperation clientOperation) 
     { 
     } 

     public void Validate(OperationDescription operationDescription) 
     { 
     } 

     public void ApplyDispatchBehavior(OperationDescription operationDescription, 
              DispatchOperation dispatchOperation) 
     { 
      MethodInfo currMethodInfo = operationDescription.SyncMethod; 
      CUSTOMOperationInvoker invoker = new CUSTOMOperationInvoker 
              (dispatchOperation.Invoker, currMethodInfo); 

      dispatchOperation.Invoker = invoker; 
      invoker.OnInvokeEnded += new EventHandler<TrackingEventArgs>(/* logWriterMethod! */); 
     } 
     #endregion 
    } 
} 

Я попытался изменить атрибут включить IServiceBehavior следующим образом:

public class TrackingBehaviorAttribute : Attribute, IServiceBehavior, IOperationBehavior 
{ 
    #region IServiceBehavior Members 
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) 
    { 

    } 
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
     foreach() 
     { 
      //Some loop to add this attribute to all service operation. 
     } 
    } 
    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
    } 

    #endregion 

Но я не могу показаться, чтобы заставить его работать. Я подхожу к этому неправильно?

UPDATE

я с помощью @ErnieL получил атрибут для работы на сервис-уровне, но теперь, когда применяется к нескольким службам я получаю следующее сообщение об ошибке при запуске хост:

"The value could not be added to the collection, as the collection already contains 
an item of the same type: 'Tracking.TrackingServiceBehaviorAttribute'. 
This collection only supports one instance of each type." 

Как мне обойти это?

ответ

3

Петля вы ищете что-то вроде этого:

public virtual void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
{ 
    foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints) 
    { 
     foreach (OperationDescription operation in endpoint.Contract.Operations) 
     { 
      // TrackingBehaviorAttribute is your code that implements IOperationBehavior 
      operation.Behaviors.Add(new TrackingBehaviorAttribute()); 
     } 
    } 
} 

Если вам нужно больше примеров Carlos Figueira Extensibility blog место для чтения.

+0

Не хотите ли вы разработать немного, этот атрибут не используется вообще. Итак, у меня есть атрибут ONE, который наследует как IServiceBehavior, так и IOperationBehavior и реализует их оба. Я вставил цикл, который вы предоставили, но поскольку я сказал, что TrackingBehaviorAttribute никогда не используется, когда применяется к службе. Я попытался отделить два атрибута и заставить IServiceBehavior вызывать IOperationBehavior, но не повезло. Meybe Im записывает это неправильно. Мне нужен только атрибут IOperationBehavior, который должен применяться во всех операциях обслуживания. – arasse

+0

Спасибо, я фактически использовал атрибут [TrackingServiceBehaviorAttribute] на интерфейсе, а не класс реализации. Я видел примеры в [Carlos Blog, который вы упомянули] (http://blogs.msdn.com/b/carlosfigueira/archive/2011/03/16/wcf-extensibility-behaviors.aspx) – arasse

1

На этот раз я попытался использовать IContractBehavior и, похоже, сработал.

public class TrackingContractBehaviorAttribute : Attribute, IContractBehavior, IOperationBehavior 
{ 
    #region IContractBehavior Members 
    public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) 
    { 
    } 
    public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime) 
    { 
    } 
    public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.DispatchRuntime dispatchRuntime) 
    { 
     foreach (OperationDescription operation in contractDescription.Operations) 
     { 
      operation.Behaviors.Add(new Tracking.TrackingContractBehaviorAttribute()); 
     } 
    } 
    public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) 
    { 
    } 
    #endregion 

    #region IOperationBehavior Members 
    public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) 
    { 

    } 

    public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) 
    { 
    } 

    public void Validate(OperationDescription operationDescription) 
    { 
    } 

    public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) 
    { 
     MethodInfo currMethodInfo = operationDescription.SyncMethod; 
     TrackingOperationInvoker invoker = new TrackingOperationInvoker(dispatchOperation.Invoker, currMethodInfo); 
//TrackingOperationInvoker is my own custom invoker to start some functions before default invoker. 

     dispatchOperation.Invoker = invoker; 
     invoker.OnInvokeEnded += new EventHandler<TrackingEventArgs>(logWriter); 
    }