WCF经常会有一些性能检测,全局异常,跨域设置,动态路由设置等,可以通过以下类实现
(1)拦截类,可以实现性能检测和全局异常处理
/// <summary>
/// 使用消息提取的对象以及参数数组,并利用对该对象调用方法,然后返回该方法的返回值和输出参数
/// </summary>
public class OperationInvoker : IOperationInvoker
{
private string _operationMethod;//方法名称
private IOperationInvoker _invoker;//原invoker
public OperationInvoker(IOperationInvoker oldInvoker, string operationMethod)
{
this._invoker = oldInvoker;
this._operationMethod = operationMethod;
}
public object[] AllocateInputs()
{
return this._invoker.AllocateInputs();
}
//System.ServiceModel.Channels.Message HandlePreflight(System.ServiceModel.Channels.Message input, string operationName)
//{
// System.ServiceModel.Channels.Message reply = System.ServiceModel.Channels.Message.CreateMessage(MessageVersion.None, operationName);
// HttpResponseMessageProperty httpResponse = new HttpResponseMessageProperty();
// httpResponse.SuppressEntityBody = true;
// httpResponse.StatusCode = System.Net.HttpStatusCode.OK;
// httpResponse.Headers.Set("Access-Control-Allow-Origin", "*");
// httpResponse.Headers.Set("Access-Control-Allow-Methods", string.Join(",", new List<string>() { "POST", "GET", "OPTIONS" }));
// reply.Properties.Add(HttpResponseMessageProperty.Name, httpResponse);
// return reply;
//}
/// <summary>
/// 从一个实例和输入对象的集合返回一个对象和输出对象的集合
/// </summary>
/// <param name="instance"></param>
/// <param name="inputs"></param>
/// <param name="outputs"></param>
/// <returns></returns>
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
this.PreInvoke(instance, inputs);
object returnValue = null;
object invokeValue;
object[] objArray = new object[0];
try
{
string operationName = "";
if (OperationContext.Current.IncomingMessageHeaders.Action != null)
{
operationName = OperationContext.Current.IncomingMessageHeaders.Action.ToString();
}
if (OperationContext.Current.IncomingMessageProperties.Keys.Contains("HttpOperationName"))
{
operationName = OperationContext.Current.IncomingMessageProperties["HttpOperationName"].ToString();
}
HttpRequestMessageProperty request =
System.ServiceModel.OperationContext.Current.IncomingMessageProperties["httpRequest"] as
HttpRequestMessageProperty;
if (request != null
&& request.Method == "OPTIONS")
{
System.ServiceModel.Channels.Message input = (System.ServiceModel.Channels.Message)inputs[0];
outputs = null;
return returnValue;
}
else
{
invokeValue = this._invoker.Invoke(instance, inputs, out objArray);
returnValue = invokeValue;
outputs = objArray;
}
}
catch (System.Exception exception)
{
returnValue = HandleException(exception, instance);
outputs = null;
}
return returnValue;
}
/// <summary>
/// 处理异常
/// </summary>
/// <returns></returns>
private ResultInfo HandleException(System.Exception exception, object instance)
{
var res = new ResultInfo();
res.Success = false;
res.Message = exception.Message;
res.Excetion = new WcfGlobalException(exception.Message, exception.StackTrace, instance, _operationMethod);
PackageServiceLib.Helper.EventManager.WriteOutput(exception.Message + exception.StackTrace, LogType.Error);
//if (exception != null)
//{
// throw exception;
//}
return res;
}
public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
{
this.PreInvoke(instance, inputs);
return this._invoker.InvokeBegin(instance, inputs, callback, state);
}
public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
{
object returnValue = null;
object invokeValue;
object[] objArray = new object[0];
try
{
invokeValue = this._invoker.InvokeEnd(instance, out outputs, result);
returnValue = invokeValue;
outputs = objArray;
}
catch (System.Exception exception)
{
returnValue = HandleException(exception, instance);
outputs = null;
}
return returnValue;
}
public bool IsSynchronous
{
get { return this._invoker.IsSynchronous; }
}
private void PreInvoke(object instance, object[] inputs)
{
}
}
(2)异常类
[DataContract]
public class WcfGlobalException
{
/// <summary>
/// 调用方法的实例
/// </summary>
[DataMember(Name = "instance")]
public string Instance { set; get; }
/// <summary>
/// 调用的方法名称
/// </summary>
[DataMember(Name = "operationMethod")]
public string OperationMethod { set; get; }
/// <summary>
/// 异常信息
/// </summary>
[DataMember(Name = "message")]
public string Message { set; get; }
/// <summary>
/// 异常trace信息
/// </summary>
[DataMember(Name = "stackTrace")]
public string StackTrace { set; get; }
public WcfGlobalException(string message, string trace, object instance, string operationName)
{
this.Instance = instance.ToString();
this.OperationMethod = operationName;
this.Message = message;
this.StackTrace = trace;
}
}
(3)行为特性标签
//BehaviorExtensionElement
public class WcfGlobalExceptionOpreationBehaviorAttribute:Attribute,IServiceBehavior
{
//public override Type BehaviorType
//{
// get { return typeof (WcfGlobalExceptionOpreationBehavior); }
//}
//protected override object CreateBehavior()
//{
// return new WcfGlobalExceptionOpreationBehavior();
//}
private readonly Type _errorHandlerType;
public WcfGlobalExceptionOpreationBehaviorAttribute(Type handlerType)
{
_errorHandlerType = handlerType;
}
public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
/// <summary>
/// 注入自定义异常处理程序
/// </summary>
/// <param name="serviceDescription"></param>
/// <param name="serviceHostBase"></param>
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
var handler = (IErrorHandler) Activator.CreateInstance(_errorHandlerType);
foreach (ChannelDispatcher dis in serviceHostBase.ChannelDispatchers)
{
dis.ErrorHandlers.Add(handler);
}
}
public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
}
}
(4)操作的拦截特性
public class WcfGlobalOperationInterceptorAttribute:Attribute,IOperationBehavior
{
private string _operationMethod;
public WcfGlobalOperationInterceptorAttribute(string methodName)
{
this._operationMethod = methodName;
}
public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.ClientOperation clientOperation)
{
}
public void ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation)
{
IOperationInvoker invoke = dispatchOperation.Invoker;
dispatchOperation.Invoker = CreateInvoker(invoke);
}
public void Validate(OperationDescription operationDescription)
{
}
protected OperationInvoker CreateInvoker(IOperationInvoker oldInvoker)
{
return new OperationInvoker(oldInvoker, this._operationMethod);
}
}
(5)服务类的拦截特性
[AttributeUsage(AttributeTargets.Class)]
public class WcfGlobalServiceInterceptorAttribute:Attribute,IServiceBehavior
{
public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
EnableCrossOriginResourceSharingBehavior crossOriginBehavior = new EnableCrossOriginResourceSharingBehavior();
foreach (var endpoint in serviceDescription.Endpoints)
{
endpoint.Behaviors.Add(crossOriginBehavior);
foreach (var operation in endpoint.Contract.Operations)
{
if (!operation.Behaviors.Any(d => d is WebGetAttribute)
&& !operation.Behaviors.Any(d => d is WebInvokeAttribute))
{
WebInvokeAttribute wia = new WebInvokeAttribute();
wia.UriTemplate = operation.Name;
wia.Method = "*";
operation.Behaviors.Add(wia);
}
bool flag = false;
foreach (var operationBehavior in operation.Behaviors)
{
if (operationBehavior is WcfGlobalOperationInterceptorAttribute)
{
flag = true;
break;
}
}
if (!flag)
{
operation.Behaviors.Add(CreateOperationInterceptor(operation.Name));
}
}
}
}
public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
}
protected WcfGlobalOperationInterceptorAttribute CreateOperationInterceptor(string operationMethod)
{
return new WcfGlobalOperationInterceptorAttribute(operationMethod);
}
}
public class CustomHeaderMessageInspector : IDispatchMessageInspector
{
Dictionary<string, string> requiredHeaders;
public CustomHeaderMessageInspector(Dictionary<string, string> headers)
{
requiredHeaders = headers ?? new Dictionary<string, string>();
}
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
return null;
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
var httpHeader = reply.Properties["httpResponse"] as HttpResponseMessageProperty;
foreach (var item in requiredHeaders)
{
httpHeader.Headers.Add(item.Key, item.Value);
}
}
}
public class EnableCrossOriginResourceSharingBehavior : BehaviorExtensionElement, IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
{
var requiredHeaders = new Dictionary<string, string>();
var allOrigin= ConfigurationManager.AppSettings["allowOrigin"].ToString();
requiredHeaders.Add("Access-Control-Allow-Origin", allOrigin);
requiredHeaders.Add("Access-Control-Request-Method", "POST,GET,PUT,DELETE,OPTIONS");
requiredHeaders.Add("Access-Control-Allow-Headers", "X-Requested-With,Content-Type");
requiredHeaders.Add("Access-Control-Allow-Credentials", "true");
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new CustomHeaderMessageInspector(requiredHeaders));
}
public void Validate(ServiceEndpoint endpoint)
{
}
public override Type BehaviorType
{
get { return typeof(EnableCrossOriginResourceSharingBehavior); }
}
protected override object CreateBehavior()
{
return new EnableCrossOriginResourceSharingBehavior();
}
}
文件下载:http://files.cnblogs.com/files/caiyongxi/WCFHelper.zip