Extending WCF using IServiceBehavior, IOperationBehavior, and IParameterInspector
[ServiceContract(Name = "PasswordGenerator")] public interface IPasswordGenerator { [OperationContract(Name = "GeneratePassword")] string GeneratePassword(); [OperationContract(Name="ParameterizedPasswordGenerator")] string GeneratePassword(int length); } public class PasswordGenerator:IPasswordGenerator { [OperationBehavior()] public string GeneratePassword() { return "You called GeneratePassword()"; } [OperationBehavior()] public string GeneratePassword(int length) { return "You called GeneratePassword(int length) overload"; } }
static void Main(string[] args) { ServiceEndpoint serviceEndpoint; Uri basePipeAddress = new Uri(@"net.Pipe://localhost/Password/Mine"); using (ServiceHost host = new ServiceHost(typeof(Password.PasswordGenerator), basePipeAddress)) { serviceEndpoint = host.AddServiceEndpoint(typeof( Password.IPasswordGenerator), new NetNamedPipeBinding(), string.Empty); host.Open(); using (var factory = new ChannelFactory<password.passwordgenerator>(new NetNamedPipeBinding())) { var proxy = factory.CreateChannel(serviceEndpoint.Address); proxy.GeneratePassword(); proxy.GeneratePassword(1500); factory.Close(); } host.Close(); } }
public static class Logger { private static void Log(string message) { try { using (var stream = new StreamWriter(@"G:\log.log", true)) { stream.WriteLine(message); stream.Flush(); stream.Close(); } } catch (Exception) { } } public static void Log(string className, string methodName, string parameter) { Log(string.Format("Class {0} called method {1} with parameter {2} @ {3}", className, methodName, parameter, DateTime.Now)); } }
First Extension
public class MyServiceBehaviorAttribute : Attribute, IServiceBehavior { public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { Logger.Log("MyServiceBehaviorAttribute", "AddBindingParameters", serviceDescription.Name); } public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { Logger.Log("MyServiceBehaviorAttribute", "ApplyDispatchBehavior", serviceDescription.Name); } public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { Logger.Log("MyServiceBehaviorAttribute", "Validate", serviceDescription.Name); } }
Second Extension
public class MyOperationBehavior:Attribute, IOperationBehavior { public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { Logger.Log("MyOperationBehavior", "AddBindingParameters", operationDescription.Name); } public void ApplyClientBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.ClientOperation clientOperation) { clientOperation.ParameterInspectors.Add(new MyParameterInspector()); Logger.Log("MyOperationBehavior", "ApplyClientBehavior", operationDescription.Name); } public void ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation) { dispatchOperation.ParameterInspectors.Add(new MyParameterInspector()); Logger.Log("MyOperationBehavior", "ApplyDispatchBehavior", operationDescription.Name); } public void Validate(OperationDescription operationDescription) { Logger.Log("MyOperationBehavior", "Validate", operationDescription.Name); } }
Third Extension
class MyParameterInspector:IParameterInspector { public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState) { Logger.Log("MyParameterInspector", "AfterCall", operationName); } public object BeforeCall(string operationName, object[] inputs) { Logger.Log("MyParameterInspector", "BeforeCall", operationName); return null; } }
[__strong__][MyServiceBehaviorAttribute()] public class PasswordGenerator:IPasswordGenerator { [OperationBehavior(),MyOperationBehavior] public string GeneratePassword() { return "You called GeneratePassword()"; } [OperationBehavior()] [MyOperationBehavior] public string GeneratePassword(int length) { return "You called GeneratePassword(int length) overload"; }
---------------------------------------------------------------------------------------------------------------------
using System; using System.Collections.Generic; using System.Text; using System.ServiceModel; using System.ServiceModel.Description; using System.ServiceModel.Dispatcher; using System.Reflection; namespace AOPAndWCF { class MyParameterInspector: IOperationBehavior, IParameterInspector { #region IOperationBehavior Members /// <summary> /// /// </summary> /// <param name="operationDescription"></param> /// <param name="bindingParameters"></param> public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { } /// <summary> /// /// </summary> /// <param name="operationDescription"></param> /// <param name="clientOperation"></param> public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { } /// <summary> /// /// </summary> /// <param name="operationDescription"></param> /// <param name="dispatchOperation"></param> public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) { dispatchOperation.ParameterInspectors.Add(this); } /// <summary> /// /// </summary> /// <param name="operationDescription"></param> public void Validate(OperationDescription operationDescription) { } #endregion /// <summary> /// 调用方法后 输出结果值 /// </summary> /// <param name="operationName"></param> /// <param name="outputs"></param> /// <param name="returnValue"></param> /// <param name="correlationState"></param> public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState) { Console.WriteLine("*************返回操作名称:" + operationName+"*************"); Console.WriteLine("*************返回操作编号:" + correlationState.ToString() + "**************"); for (int i = 0; i < outputs.Length; i++) { Type T = outputs[i].GetType(); Console.WriteLine("返回操作参数" + i.ToString() + " 类型为:" + T.ToString()); Console.WriteLine("返回操作参数" + i.ToString() + " ToString为:" + outputs[i].ToString()); Console.WriteLine("返回操作参数" + i.ToString() + " 属性:"); PropertyInfo[] PIs = T.GetProperties(); foreach (PropertyInfo PI in PIs) { Console.Write(PI.Name + ":"); Console.WriteLine(PI.GetValue(outputs[i], null)); } } Type Treturn = returnValue.GetType(); Console.WriteLine("操作返回值" + " 类型为:" + Treturn.ToString()); Console.WriteLine("操作返回值" + " ToString为:" + Treturn.ToString()); Console.WriteLine("操作返回值" + " 属性:"); if (Treturn.ToString() != "System.String") { PropertyInfo[] PIreturns = Treturn.GetProperties(); foreach (PropertyInfo PI in PIreturns) { Console.Write(PI.Name + ":"); Console.WriteLine(PI.GetValue(returnValue, null)); } } } /// <summary> /// 调用方法前 输出参数值 /// </summary> /// <param name="operationName"></param> /// <param name="inputs"></param> /// <returns></returns> public object BeforeCall(string operationName, object[] inputs) { Guid guid = Guid.NewGuid(); Console.WriteLine("*************调用操作名称:" + operationName+"**************"); Console.WriteLine("*************调用操作编号:" + guid.ToString () + "**************"); for (int i = 0; i < inputs.Length ; i++) { Type T = inputs[i] .GetType (); Console.WriteLine("操作参数"+i.ToString ()+" 类型为:"+T.ToString ()); Console.WriteLine("操作参数" + i.ToString() + " ToString为:" + inputs[i].ToString()); Console.WriteLine("操作参数" + i.ToString() + " 属性:"); PropertyInfo [] PIs = T.GetProperties(); foreach (PropertyInfo PI in PIs) { Console.Write ( PI.Name +":"); Console.WriteLine (PI.GetValue(inputs[i], null)); } } return guid; } } }
using System; using System.Collections.Generic; using System.Text; using System.ServiceModel ; using System.ServiceModel.Description; namespace AOPAndWCF { public class MyServiceHost:ServiceHost { /// <summary> /// 构造函数 /// </summary> /// <param name="serviceType">服务类型</param> /// <param name="baseAddresses">基地址</param> public MyServiceHost(Type serviceType, params Uri[] baseAddresses) : base(serviceType, baseAddresses) { } /// <summary> /// 应用配置文件设置 /// </summary> protected override void ApplyConfiguration() { base.ApplyConfiguration(); //加入参数检查服务 addguidvalidation(); } /// <summary> ///加入参数检查服务 /// </summary> private void addguidvalidation() { //加入参数检查服务 int endpointscount = this.Description.Endpoints.Count; MyParameterInspector mypi = new MyParameterInspector(); for (int i = 0; i < endpointscount; i++) { if (this.Description.Endpoints[i].Contract.Name != "IMetadataExchange") { int Operationscount = this.Description.Endpoints[i].Contract.Operations.Count; for (int j = 0; j < Operationscount; j++) { this.Description.Endpoints[i].Contract.Operations[j].Behaviors.Add(mypi); } } } } } }
using System; using System.Collections.Generic; using System.Text; namespace AOPAndWCF { class Program { static void Main(string[] args) { MyServiceHost msh = new MyServiceHost(typeof(WcfServiceLibrary.Service1 )); msh.Open(); Console.WriteLine ("服务已开启,回车关闭服务"); Console.ReadLine(); msh.Close(); } } }