溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何通過一個ASP.NET程序模擬WCF基本架構(gòu)

發(fā)布時間:2021-10-28 09:31:07 來源:億速云 閱讀:149 作者:柒染 欄目:編程語言

如何通過一個ASP.NET程序模擬WCF基本架構(gòu),針對這個問題,這篇文章詳細(xì)介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

目的在于對WCF技術(shù)剖析的補充,對一些內(nèi)容進(jìn)行展開講述,同時會囊括很多由于篇幅的原因忍痛割棄的內(nèi)容。

我將會對WCF的基本架構(gòu)作一個大致的講解。不過,一改傳統(tǒng)對WCF的工作流程進(jìn)行平鋪直敘,我將另辟蹊徑,借助于我們熟悉的ASP.NET作為請求處理平臺,通過一個簡單的托管程序模擬整個WCF客戶端和服務(wù)端的架構(gòu)。

WCF框架處理流程和涉及的組件

我們的模擬程序?qū)⒛愦罱ㄒ粋€迷你版的WCF框架,為了展示W(wǎng)CF整個處理流程中使用到一些特殊組件。我們首先來簡單介紹一下對于一個簡單的WCF服務(wù)調(diào)用,WCF的客戶端和服務(wù)端框架的處理流程,和該流程的每一個階段都使用那些重要組件。

下面的列表列出了WCF服務(wù)端框架對于處理一個簡單的WCF服務(wù)調(diào)用請求所提供的功能,以及相應(yīng)的功能承載的組件:

請求消息的接收和回復(fù)消息的發(fā)送:服務(wù)端在傳輸層監(jiān)聽與接收來自客戶的請求,并將經(jīng)過編碼后的回復(fù)消息通過傳輸層發(fā)送到客戶端

請求消息的解碼和回復(fù)消息的編碼:將接收到的字節(jié)數(shù)組通過解碼生成請求消息對象,并將回復(fù)消息通過編程轉(zhuǎn)化成字節(jié)組。消息的編碼和解碼通過MessageEncoder完成,而MessageEncoderFactory負(fù)責(zé)創(chuàng)建該對象

請求消息的反序列化和回復(fù)消息的序列化:對請求消息進(jìn)行反序列化,為服務(wù)操作的執(zhí)行生成相應(yīng)的輸入?yún)?shù),以及將服務(wù)操作執(zhí)行的結(jié)果(返回值或者ref/out參數(shù))序列化,并生成回復(fù)消息。序列化和反序列化通過DispatchMessageFormatter完成

服務(wù)對象的創(chuàng)建:創(chuàng)建或者激活服務(wù)對象實例,IntanceProvider用于服務(wù)對象的創(chuàng)建或獲取

服務(wù)操作的執(zhí)行:調(diào)用創(chuàng)建的服務(wù)對象的操作方法,并傳入經(jīng)過反序列化生成的輸入?yún)?shù)。OperationInvoker完成對服務(wù)操作的最終執(zhí)行

較之服務(wù)端的流程,客戶端的流程顯得相對簡單,僅僅包含以下三個必需的階段:

請求消息的序列化和回復(fù)消息的反序列化:生成請求消息并將輸入?yún)?shù)序列化到請求消息中,以及對回復(fù)消息進(jìn)行反序列化,轉(zhuǎn)化成方法調(diào)用的返回值或者ref/out參數(shù)。序列化和反序列化通過ClienthMessageFormatter完成

請求消息的編碼和回復(fù)消息的解碼:對請求消息進(jìn)行編碼生成字節(jié)數(shù)組供傳輸層發(fā)送,以及將傳輸層接收到的字節(jié)數(shù)組解碼生成恢復(fù)消息。消息的編碼和解碼通過MessageEncoder完成,而MessageEncoderFactory負(fù)責(zé)創(chuàng)建該對象

請求消息的發(fā)送和回復(fù)消息的接收:在傳輸層將經(jīng)過編碼的請求消息發(fā)送到服務(wù)端,以及將接收來自服務(wù)端的恢復(fù)消息

如何通過一個ASP.NET程序模擬WCF基本架構(gòu) 
圖1 精簡版WCF客戶端與服務(wù)端組件

圖1反映了進(jìn)行服務(wù)調(diào)用的必要步驟和使用到的相關(guān)WCF組件。在本案例演示中,我們需要做的就是手工創(chuàng)建這些組件,并通過我們自己的代碼利用它們搭建一個建議版的WCF框架。如果讀者能夠?qū)Ρ景咐膶崿F(xiàn)有一個清晰的理解,相信對于整個WCF的框架就不會感到陌生了。

圖2顯示了本案例解決方案的基本結(jié)構(gòu),總共分三個項目。Contracts用于定義服務(wù)契約,被服務(wù)端和客戶端引用??蛻舳送ㄟ^一個Console應(yīng)用模擬,而服務(wù)端則通過一個ASP.NET Website實現(xiàn)。

如何通過一個ASP.NET程序模擬WCF基本架構(gòu) 
圖2 WCF框架模擬案例應(yīng)用結(jié)構(gòu)

步驟一、通過服務(wù)契約類型創(chuàng)建相關(guān)組件

WCF在整個服務(wù)調(diào)用生命周期的不同階段,會使用到不同的組件。我們通過一個方法將服務(wù)端和客戶端所需的所有組件都創(chuàng)建出來,為此,我們在Contracts項目中添加了一個Utility類型,在Create< T>方法中創(chuàng)建所有的組件并通過輸出參數(shù)的形式返回,泛型類型T表示的是服務(wù)契約類型。在該方法中,輸出參數(shù)encoderFactory被服務(wù)端和客戶端用于消息的編碼和解碼,clientFormatters和dispatchFormatters以字典的形式包含了基于服務(wù)操作的IClientMessageFormatter和IDispatchMessageFormatter,其中clientFormatters和dispatchFormatters的Key分別為操作名稱和操作對應(yīng)的Action。同樣通過字典形式返回的operationInvokers和methods用于在服務(wù)端執(zhí)行相應(yīng)的操作方法,Key同樣為操作對應(yīng)的Action。

public static class Utility  {      public static void Create< T>(out MessageEncoderFactory encoderFactory,          out IDictionary< string, IClientMessageFormatter> clientFormatters,          out IDictionary< string, IDispatchMessageFormatter> dispatchFormatters,          out IDictionary< string, IOperationInvoker> operationInvokers,          out IDictionary< string, MethodInfo> methods)      {          //省略實現(xiàn)      }  }

具體的實現(xiàn)如下,由于在WCF框架中使用的MessageEncoderFactory(TextMessageEncoderFactory)、MessageFormatter(DataContractSerializerOperationFormatter)和OperationInvoker(SyncMethodInvoker)都是一些內(nèi)部類型,所以只能通過反射的方式創(chuàng)建它們。而操作名稱和Action也主要通過反射的原理解析應(yīng)用在服務(wù)方法上的OperationContractAttribute得到。

public static void Create< T>(out MessageEncoderFactory encoderFactory,      out IDictionary< string, IClientMessageFormatter> clientFormatters,      out IDictionary< string, IDispatchMessageFormatter> dispatchFormatters,      out IDictionary< string, IOperationInvoker> operationInvokers,      out IDictionary< string, MethodInfo> methods)  {      //確保類型T是應(yīng)用了ServiceContractAttribute的服務(wù)契約      object[] attributes = typeof(T).GetCustomAttributes(typeof(ServiceContractAttribute), false);      if (attributes.Length == 0)      {          throw new InvalidOperationException(string.Format("The type \"{0}\" is not a ServiceContract!", typeof(T).AssemblyQualifiedName));      }        //創(chuàng)建字典保存IClientMessageFormatter、IDispatchMessageFormatter、IOperationInvoker和MethodInfo      clientFormatters = new Dictionary< string, IClientMessageFormatter>();      dispatchFormatters = new Dictionary< string, IDispatchMessageFormatter>();      operationInvokers = new Dictionary< string, IOperationInvoker>();      methods = new Dictionary< string, MethodInfo>();        //MessageEncoderFactory      string encoderFactoryType = "System.ServiceModel.Channels.TextMessageEncoderFactory,System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";      encoderFactory = (MessageEncoderFactory)Activator.CreateInstance(Type.GetType(encoderFactoryType), MessageVersion.Default, Encoding.UTF8, int.MaxValue, int.MaxValue, new XmlDictionaryReaderQuotas());    //得到OperationDecription列表  string defaultNamespace = "http://tempuri.org/";      ServiceContractAttribute serviceAttribute = (ServiceContractAttribute)attributes[0];      string serviceNamepace = string.IsNullOrEmpty(serviceAttribute.Namespace) ? defaultNamespace : serviceAttribute.Namespace;      string serviceName = string.IsNullOrEmpty(serviceAttribute.Name) ? typeof(T).Name : serviceAttribute.Name;      var operations = ContractDescription.GetContract(typeof(T)).Operations;        //得到具體的IClientMessageFormatter、IDispatchMessageFormatter和IOperationInvoker的具體類型      //IClientMessageFormatter+IDispatchMessageFormatter:DataContractSerializerOperationFormatter      //IOperationInvoker:SyncMethodInvoker      string formatterTypeName = "System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter,System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";      Type formatterType = Type.GetType(formatterTypeName);      ConstructorInfo formatterConstructor = formatterType.GetConstructor(new Type[] { typeof(OperationDescription), typeof(DataContractFormatAttribute), typeof(DataContractSerializerOperationBehavior) });      string operationInvokerTypeName = "System.ServiceModel.Dispatcher.SyncMethodInvoker,System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";      Type operationInvokerType = Type.GetType(operationInvokerTypeName);        foreach (MethodInfo method in typeof(T).GetMethods())      {          attributes = method.GetCustomAttributes(typeof(OperationContractAttribute), true);          if (attributes.Length > 0)          {              OperationContractAttribute operationAttribute = (OperationContractAttribute)attributes[0];              string operationName = string.IsNullOrEmpty(operationAttribute.Name) ? method.Name : operationAttribute.Name;              //通過OperationContractAttribute得到Action              string action;              if (string.IsNullOrEmpty(operationAttribute.Action))              {                  action = string.Format("{0}{1}/{2}", serviceNamepace, serviceName, operationName);              }              else             {                  action = operationAttribute.Action;              }                OperationDescription operation = operations.Where(op => op.Name == operationName).ToArray< OperationDescription>()[0];              //通過反射創(chuàng)建DataContractSerializerOperationFormatter對象              object formatter = formatterConstructor.Invoke(new object[] { operation, new DataContractFormatAttribute(), null });              clientFormatters.Add(operationName, formatter as IClientMessageFormatter);              dispatchFormatters.Add(action, formatter as IDispatchMessageFormatter);                //通過反射創(chuàng)建SyncMethodInvoker對象              IOperationInvoker operationInvoker = (IOperationInvoker)Activator.CreateInstance(operationInvokerType, method);              operationInvokers.Add(action, operationInvoker);              methods.Add(action, method);          }  }

步驟二、創(chuàng)建服務(wù)契約和實現(xiàn)服務(wù)

接下來為本案例創(chuàng)建一個服務(wù)契約和實現(xiàn)該契約。服務(wù)契約定義在Contracts項目,具體的服務(wù)實現(xiàn)在模擬服務(wù)端的ASP.NET Web站點中。簡單起見,依然沿用計算服務(wù)的例子。

namespace Artech.WcfFrameworkSimulator.Contracts  {      [ServiceContract(Namespace = "http://www.artech.com/")]      public interface ICalculator      {          [OperationContract]          double Add(double x, double y);      }  }      public class CalculatorService : ICalculator  {      public double Add(double x, double y)      {          return x + y;      }  }

步驟三、實現(xiàn)服務(wù)端對服務(wù)調(diào)用請求的處理

我們通過一個ASP.NET的Web Page來模擬WCF服務(wù)端對服務(wù)請求的處理,下面的Calculator類型相關(guān)的代碼實際上就是Calculator.aspx的后臺代碼(Code Behind)。整個處理流程不算復(fù)雜。在構(gòu)造函數(shù)中,調(diào)用Utility的Create< ICalculator>方法,將所需的組件進(jìn)行初始化,而具體的服務(wù)調(diào)用請求處理的邏輯在直接寫在Web Page的Load事件中。

首先,通過MessageCoderFactory創(chuàng)建MessageEncoder對接收到的以HttpRequest形式體現(xiàn)的服務(wù)調(diào)用請求進(jìn)行解碼,并生成請求消息。通過請求消息得到當(dāng)前服務(wù)操作的Action屬性后,在初始化過程中得到的基于服務(wù)契約所有MethodInfo列表中,根據(jù)該Action得到當(dāng)前操作對應(yīng)的MethodInfo對象。借助于MethodInfo對象得到操作方法的輸入?yún)?shù)和輸出參數(shù)數(shù)量后,創(chuàng)建兩個對象數(shù)組,分別用于保存通過DispatchMessageFormatter對象對于請求消息進(jìn)行反序列化得到的輸入?yún)?shù),和通過OperationInvoker執(zhí)行操作方法得到的輸出參數(shù)。在OperationInvoker執(zhí)行操作方法之前,通過反射的方式直接創(chuàng)建服務(wù)對象,這一步在真正的WCF框架中是通過InstanceProvider實現(xiàn)的。

通過OperationInvoker執(zhí)行操作方法的結(jié)果有兩種形式:返回值和輸出參數(shù)(包括引用參數(shù))。它們通過被傳入DispatchMessageFormatter被序列化并生成回復(fù)消息對象?;貜?fù)消息通過MessageCoderFactory創(chuàng)建MessageEncoder進(jìn)行編碼后通過HttpResponse返回。

public partial class Calculator : System.Web.UI.Page  {      private static MessageVersion messageversion = MessageVersion.Default;      private static MessageEncoderFactory encoderFactory;      private static IDictionary< string, IDispatchMessageFormatter> dispatchFormatters;      private static IDictionary< string, IOperationInvoker> operationInvokers;      private static IDictionary< string, MethodInfo> methods;       protected Calculator()      {          IDictionary< string, IClientMessageFormatter> clientFormatters;          Utility.Create< ICalculator>(out encoderFactory, out clientFormatters, out dispatchFormatters, out operationInvokers, out methods);      }       protected void Page_Load(object sender, EventArgs e)      {          //對HttpPRequest進(jìn)行解碼生成請求消息對象          Message request = encoderFactory.Encoder.ReadMessage(this.Request.InputStream, int.MaxValue, "application/soap+xml; charset=utf-8");           //通過請求消息得到代表服務(wù)操作的Action          string action = request.Headers.Action;           //通過Action從MethodInfo字典中獲取服務(wù)操作對應(yīng)的MethodInfo對象          MethodInfo method = methods[action];           //得到輸出參數(shù)的數(shù)量          int outArgsCount = 0;          foreach (var parameter in method.GetParameters())          {              if (parameter.IsOut)              {                  outArgsCount++;              }          }           //創(chuàng)建數(shù)組容器,用于保存請求消息反序列后生成的輸入?yún)?shù)對象          int inputArgsCount = method.GetParameters().Length - outArgsCount;          object[] parameters = new object[inputArgsCount];          dispatchFormatters[action].DeserializeRequest(request, parameters);           List< object> inputArgs = new List< object>();          object[] outArgs = new object[outArgsCount];          //創(chuàng)建服務(wù)對象,在WCF中服務(wù)對象通過InstanceProvider創(chuàng)建          object serviceInstance = Activator.CreateInstance(typeof(CalculatorService));          //執(zhí)行服務(wù)操作          object result = operationInvokers[action].Invoke(serviceInstance, parameters, out outArgs);          //將操作執(zhí)行的結(jié)果(返回值或者輸出參數(shù))序列化生成回復(fù)消息          Message reply = dispatchFormatters[action].SerializeReply(messageversion, outArgs, result);          this.Response.ClearContent();          this.Response.ContentEncoding = Encoding.UTF8;          this.Response.ContentType = "application/soap+xml; charset=utf-8";          //對回復(fù)消息進(jìn)行編碼,并將編碼后的消息通過HttpResponse返回          encoderFactory.Encoder.WriteMessage(reply, this.Response.OutputStream);          this.Response.Flush();      }  }

步驟四、實現(xiàn)客戶端對服務(wù)調(diào)用請求的處理

由于在客戶端對服務(wù)請求的處理是通過一個RealProxy(ServiceChannelFactory)實現(xiàn)的,為了真實模擬WCF處理框架,在這里通過一個自定義RealProxy來實現(xiàn)客戶端相關(guān)的服務(wù)調(diào)用請求的處理。下面代碼中定義的ServiceRealProxy< IContract>就是這樣一個自定義RealProxy。

用于處理服務(wù)調(diào)用請求的相關(guān)組件對象,比如MessageEncoderFactory和IClientMessageFormatter字典,以及所需的屬性,比如消息的版本和服務(wù)的目的地址,通過構(gòu)造函數(shù)指定。而具體的請求處理實現(xiàn)在重寫的Invoke方法之中。首先通過解析應(yīng)用在當(dāng)前方法的上面的OperationContractAttribute得到服務(wù)操作的名稱,以此為Key從IClientMessageFormatter字典中得到當(dāng)前服務(wù)操作對應(yīng)的IClientMessageFormatter對象。當(dāng)前操作方法調(diào)用的輸入?yún)?shù)通過IClientMessageFormatter對象進(jìn)行序列化后生成請求消息。為請求消息添加必要的尋址報頭后,通過MessageEncoderFactory創(chuàng)建的MessageEncoder對請求消息進(jìn)行編碼。經(jīng)過編碼的消息以HttpRequest的形式發(fā)送到服務(wù)端,從而完成了服務(wù)調(diào)用請求的發(fā)送。

服務(wù)調(diào)用的結(jié)果通過HttpResponse的形式返回后,先通過MessageEncoder對其解碼,并生成回復(fù)消息?;貜?fù)消息通過IClientMessageFormatter進(jìn)行反序列化后,在消息中以XML InfoSet實行體現(xiàn)的結(jié)果被轉(zhuǎn)化成具體的對象,這些對象被最終影射為方法調(diào)用的返回值和輸出參數(shù)(包含引用參數(shù))。

namespace Artech.WcfFrameworkSimulator.Client  {      public class ServiceRealProxy< IContract> : RealProxy      {          private Uri _remoteAddress;          private IDictionary< string, IClientMessageFormatter> _messageFormatters;          private MessageVersion _messageVersion = MessageVersion.Default;          private MessageEncoderFactory _messageEncoderFactory;           public ServiceRealProxy(MessageVersion messageVersion, Uri address, IDictionary< string, IClientMessageFormatter> messageFormaters, MessageEncoderFactory messageEncoderFactory)              : base(typeof(IContract))          {              object[] attribute = typeof(IContract).GetCustomAttributes(typeof(ServiceContractAttribute), false);              if (attribute.Length == 0)              {                  throw new InvalidOperationException(string.Format("The type \"{0}\" is not a ServiceContract!", typeof(IContract).AssemblyQualifiedName));              }              this._messageVersion = messageVersion;              this._remoteAddress = address;              this._messageFormatters = messageFormaters;              this._messageEncoderFactory = messageEncoderFactory;          }           public override IMessage Invoke(IMessage msg)          {              IMethodCallMessage methodCall = (IMethodCallMessage)msg;               //Get Operation name.              object[] attributes = methodCall.MethodBase.GetCustomAttributes(typeof(OperationContractAttribute), true);              if (attributes.Length == 0)              {                  throw new InvalidOperationException(string.Format("The method \"{0}\" is not a valid OperationContract.", methodCall.MethodName));              }              OperationContractAttribute attribute = (OperationContractAttribute)attributes[0];              string operationName = string.IsNullOrEmpty(attribute.Name) ? methodCall.MethodName : attribute.Name;               //序列化請求消息              Message requestMessage = this._messageFormatters[operationName].SerializeRequest(this._messageVersion, methodCall.InArgs);               //添加必要的WS-Address報頭              EndpointAddress address = new EndpointAddress(this._remoteAddress);              requestMessage.Headers.MessageId = new UniqueId(Guid.NewGuid());              requestMessage.Headers.ReplyTo = new EndpointAddress("http://www.w3.org/2005/08/addressing/anonymous");              address.ApplyTo(requestMessage);               //對請求消息進(jìn)行編碼,并將編碼生成的字節(jié)發(fā)送通過HttpWebRequest向服務(wù)端發(fā)送              HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(this._remoteAddress);              webRequest.Method = "Post";              webRequest.KeepAlive = true;              webRequest.ContentType = "application/soap+xml; charset=utf-8";              ArraySegment< byte> bytes = this._messageEncoderFactory.Encoder.WriteMessage(requestMessage, int.MaxValue, BufferManager.CreateBufferManager(long.MaxValue, int.MaxValue));              webRequest.ContentLength = bytes.Array.Length;              webRequest.GetRequestStream().Write(bytes.Array, 0, bytes.Array.Length);              webRequest.GetRequestStream().Close();              WebResponse webResponse = webRequest.GetResponse();               //對HttpResponse進(jìn)行解碼生成回復(fù)消息.              Message responseMessage = this._messageEncoderFactory.Encoder.ReadMessage(webResponse.GetResponseStream(), int.MaxValue);               //回復(fù)消息進(jìn)行反列化生成相應(yīng)的對象,并映射為方法調(diào)用的返回值或者ref/out參數(shù)              object[] allArgs = (object[])Array.CreateInstance(typeof(object), methodCall.ArgCount);              Array.Copy(methodCall.Args, allArgs, methodCall.ArgCount);              object[] refOutParameters = new object[GetRefOutParameterCount(methodCall.MethodBase)];              object returnValue = this._messageFormatters[operationName].DeserializeReply(responseMessage, refOutParameters);              MapRefOutParameter(methodCall.MethodBase, allArgs, refOutParameters);               //通過ReturnMessage的形式將返回值和ref/out參數(shù)返回              return new ReturnMessage(returnValue, allArgs, allArgs.Length, methodCall.LogicalCallContext, methodCall);          }           private int GetRefOutParameterCount(MethodBase method)          {              int count = 0;              foreach (ParameterInfo parameter in method.GetParameters())              {                  if (parameter.IsOut || parameter.ParameterType.IsByRef)                  {                      count++;                  }              }              return count;          }           private void MapRefOutParameter(MethodBase method, object[] allArgs, object[] refOutArgs)          {              List< int> refOutParamPositionsList = new List< int>();              foreach (ParameterInfo parameter in method.GetParameters())              {                  if (parameter.IsOut || parameter.ParameterType.IsByRef)                  {                      refOutParamPositionsList.Add(parameter.Position);                  }              }              int[] refOutParamPositionArray = refOutParamPositionsList.ToArray();              for (int i = 0; i <  refOutArgs.Length; i++)              {                  allArgs[refOutParamPositionArray[i]] = refOutArgs[i];              }          }      }  }

在真正的WCF客戶端框架下,客戶端通過ChannelFactory< T>創(chuàng)建服務(wù)代理對象進(jìn)行服務(wù)的調(diào)用,在這里我們也創(chuàng)建一個完成相似功能的工廠類型: SerivceProxyFactory< T>,泛型類型T代表服務(wù)契約類型。

用于創(chuàng)建服務(wù)代理的Create方法很簡單:先通過Utility.Create< T>方法創(chuàng)建客戶端進(jìn)行服務(wù)調(diào)用必須的相關(guān)組件對象,通過這些對象連同該方法的參數(shù)(消息版本和服務(wù)目的地址)創(chuàng)建ServiceRealProxy< T>對象,最終返回的是該RealProxy的TransparentProxy。

namespace Artech.WcfFrameworkSimulator.Client  {      public static class SerivceProxyFactory< T>      {          public static T Create(MessageVersion messageVersion, Uri remoteAddress)          {              MessageEncoderFactory encoderFactory;              IDictionary< string, IClientMessageFormatter> clientFormatters;              IDictionary< string, IDispatchMessageFormatter> dispatchFormatters;              IDictionary< string, IOperationInvoker> operationInvokers;              IDictionary< string, MethodInfo> methods;              Utility.Create< T>(out encoderFactory, out clientFormatters, out dispatchFormatters, out operationInvokers, out methods);              ServiceRealProxy< T> realProxy = new ServiceRealProxy< T>(messageVersion, remoteAddress, clientFormatters, encoderFactory);              return (T)realProxy.GetTransparentProxy();          }      }  }

那么在最終的客戶端代碼中就可以借助SerivceProxyFactory< T>創(chuàng)建服務(wù)代理進(jìn)行服務(wù)調(diào)用了,而這里服務(wù)的目標(biāo)地址實際上是上面用于模擬WCF服務(wù)端框架的.aspx Web Page的地址。

namespace Artech.WcfFrameworkSimulator.Client  {      class Program      {          static void Main(string[] args)          {              ICalculator calculator = SerivceProxyFactory< ICalculator>.Create(MessageVersion.Default, new Uri("http://localhost/Artech.WcfFrameworkSimulator/Calculator.aspx"));              double result = calculator.Add(1, 2);              Console.WriteLine("x + y = {2} when x = {0} and y = {1}", 1, 2, result);          }      }  }

執(zhí)行結(jié)果:

x + y = 3 when x = 1 and y = 2

關(guān)于如何通過一個ASP.NET程序模擬WCF基本架構(gòu)問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI