我在[OperationContract]上使用以下[TrackingBehaviorAttribute]和自定义IOperationInvoker,一切都很好。
但我找到了一种方法,可以在接口级别([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
但我似乎无法让它发挥作用。我接近这个错误吗?
更新
我在@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."
我该如何解决这个问题?
答案 0 :(得分: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,请阅读。
答案 1 :(得分: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);
}