WCf是集大成者,具有其他微軟的很多技術,其中分布式上很多借助於Remoting,所以研究一下Remoting有助於理解WCF
提到Remoting就不得不涉及到MarshalByRefObject這個對象,網絡上對這個詞語的解釋非常的模糊不清,特別是說“跨域訪問,Remoting是引用傳遞,不是值傳遞”,而沒有講“引用傳遞”到底是傳的什麼東西,有的地方確實說了通過ObjRef對象 傳遞需要交互的所有內容信息,但是更多的是對“引用傳遞”沒有清楚的認識,或者說是通過其他方式來理解“引用傳遞”而不是通過“引用傳遞”來更好的理解Remoting,這種邏輯思維方式,特別容易產生囫囵吞棗的模糊概念,看似明白,其實不明白。
為了理解引用傳遞,寫了一個例子,可能有助於理解 代碼
定義Interface
public interface IPersonService { String HelloMethod(String name); }
定義 Implement
public class PersonService : MarshalByRefObject, IPersonService { public String HelloMethod(String name) { Console.WriteLine( "Server Hello.HelloMethod : {0}", name); return "Hi there " + name; } }
static void Main(string[] args) { //TCP協議傳輸消息的信道實現 TcpChannel chan1 = new TcpChannel(8085); //為遠程調用實現使用HTTP協議傳輸消息的客戶端通道 HttpChannel chan2 = new HttpChannel(8086); //提供幫助進行遠程處理信道注冊、解析和URL發現的靜態方法。無法繼承此類 ChannelServices.RegisterChannel(chan1, false); ChannelServices.RegisterChannel(chan2, false); //提供多種配置遠程結構的靜態方法 RemotingConfiguration.RegisterWellKnownServiceType ( //typeof(HelloServer), typeof(PersonService), "SayHello", WellKnownObjectMode.Singleton ); System.Console.WriteLine("Press Enter key to exit"); System.Console.ReadLine(); }定義Client
class Program { static void Main(string[] args) { TcpChannel chan1 = new TcpChannel(); ChannelServices.RegisterChannel(chan1,false); //Activator包含特定的方法,用以在本地或從遠程創建對象類型、或獲取對現有遠程對象的引用。無法繼承此類 IPersonService obj1 = (IPersonService)Activator.GetObject( typeof(IPersonService),// typeof(HelloServer), "tcp://localhost:8085/SayHello"); if (obj1 == null) { System.Console.WriteLine( "Could not locate TCP server"); } //使用HTTP通道得到遠程對象 HttpChannel chan2 = new HttpChannel(); ChannelServices.RegisterChannel(chan2,false); IPersonService obj2 = (IPersonService)Activator.GetObject( typeof(IPersonService),// typeof(HelloServer), "http://localhost:8086/SayHello"); if (obj2 == null) { System.Console.WriteLine( "Could not locate HTTP server"); } Console.WriteLine( "Client1 TCP HelloMethod {0}", obj1.HelloMethod("Caveman1")); Console.WriteLine( "Client2 HTTP HelloMethod {0}", obj2.HelloMethod("Caveman2")); Console.ReadLine(); } }
注意,客戶端使用的 “IPersonService”接口,對於客戶端來講是不知道接口的實例類的,
客戶端方法的調用也只是通過Activator生成的代理對象把調用的信息、鏈接信息等等進行打包,
服務端接收到打包過來的信息後,根據打包信息內容,對相應的類和方法進行操作,比如:創建(調用)服務實體,對方法進行調用,把返回值進行打包並傳輸給客戶端端,裡邊具體的邏輯還需要繼續研究
這裡只想說明一點,“Remoting傳輸的引用”,到底是什麼意思,免得誤解。
值傳遞只是將參數復制一份而已,函數進行操作的是另一個參數,只是另一個參數的值和傳遞的參數值是相同的。
而地址傳遞是直接把參數的地址傳遞給函數,這時函數是直接對原來的參數進行操作的。所以值會變化。
至於為什麼是只有值傳遞,你可以參考一下這個網址:www.javaeye.com/topic/214404
這個問題,解釋起來還有點復雜,下面我舉一些例子來說明。
首先,我們定義一個對象,來做為測試之用。
public class TestClass
{
public int Number { get; set; }
}
然後定義幾個函數,分別來看看所謂引用類型的參數傳遞
class Program
{
static void Main(string[] args)
{
TestClass test = new TestClass();
Console.WriteLine( "default: {0}", test.Number);
Function1(test);
Console.WriteLine("after Function1: {0}", test.Number);
Function2(test);
Console.WriteLine("after Function2: {0}", test.Number);
Function3(ref test);
Console.WriteLine("after Function3: {0}", test.Number);
Function4(out test);
Console.WriteLine("after Function4: {0}", test.Number);
Console.ReadKey();
}
static void Function1(TestClass obj)
{
obj.Number = 1;
}
static void Function2(TestClass obj)
{
obj = new TestClass();
obj.Number = 2;
}
static void Function3(ref TestClass obj)
{
obj = new TestClass();
obj.Number = 3;
}
static void Function4(out TestClass obj)
{
obj = new TestClass();
obj.Number = 4;
}
}
對這段代碼執行一下,我們看一下結果:
default: 0
after Function1: 1
after Function2: 1
after Function3: 3
after Function4: 4
可以看出來,只有 Function2 沒有達到我們預期的效果,為什麼呢?它不是引用傳遞的嗎?
我想這就是樓主所面臨的問題了吧
現在我們就拿這個......余下全文>>