2012-04-10 60 views
6

我已經創建了三個組件的客戶端的端點。一個網站,一個WCF服務和一個合約程序集,它們包含了服務實現的接口。我想用溫莎城堡到客戶(網站)上創建爲我服務,讓我不必在網站進行,我希望使用的每個服務的web.config文件的端點。使用溫莎城堡WcfFacility創建

我想看看來件裝配,並得到一個命名空間中的所有業務接口。現在,對於每個服務,在向容器註冊組件時,我都有類似以下內容。

container.Register(Component.For<ChannelFactory<IMyService>>().DependsOn(new { endpointConfigurationName = "MyServiceEndpoint" }).LifeStyle.Singleton); 
container.Register(Component.For<IMyService>().UsingFactoryMethod((kernel, creationContext) => kernel.Resolve<ChannelFactory<IMyService>>().CreateChannel()).LifeStyle.PerWebRequest); 

和我的web.config我已經設置代碼。

<system.serviceModel> 
     <extensions> 
     <behaviorExtensions> 
      <add name="AuthToken" type="MyNamespace.Infrastructure.AuthTokenBehavior, MyNamespace.Contracts" /> 
     </behaviorExtensions> 
     </extensions> 
     <behaviors> 
     <endpointBehaviors> 
      <behavior> 
       <AuthToken /> 
      </behavior> 
     </endpointBehaviors> 
     </behaviors> 

     <bindings> 
     <wsHttpBinding> 
      <binding maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"> 
       <readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647"></readerQuotas> 
       <security mode="None" /> 
      </binding> 
     </wsHttpBinding> 
     </bindings> 

     <client> 
     <endpoint name="MyServiceEndpoint" address="http://someurl/MyService.svc" binding="wsHttpBinding" contract="MyNamespace.Contracts.IMyService"></endpoint> 
     </client> 
    </system.serviceModel> 

我結束了與多個服務端點,所有的外觀幾乎一模一樣,當我們部署到客戶機,他們必須設置每個端點的地址,即使基本URL是每一個相同的。

我想在我的web.config中通過代碼抓取一個基礎url,然後使用合約程序集上的反射向容器註冊服務。我確實需要上述配置文件中的專用端點行爲。

在哪裏,所以我開始? WcfFacility看起來不錯,但是DOCO有點欠缺...

回答

12

我同意wcf設施的文檔缺乏,這很令人傷心,因爲它是一個非常棒的工具,如果人們不願意, T選用它,因爲他們不能上手,所以讓我看看,如果我可以,如果我可以幫你出一點點...

讓我們創建一個有三個項目申請:

  1. 類庫共享合同
  2. 充當服務器控制檯應用程序
  3. 充當客戶

的想法控制檯應用程序是,我們希望能夠在我們註冊服務,使用該服務的名稱,並共享一個基礎URL(我認爲這是你問的是什麼如果沒有,希望你可以從這裏推斷出來)。因此,首先,共享合同只是有這個它(沒什麼特別的,正常的WCF票價):

[ServiceContract] 
public interface IMyService1 
{ 
    [OperationContract] 
    void DoSomething(); 
} 

[ServiceContract] 
public interface IMyService2 
{ 
    [OperationContract] 
    void DoSomethingToo(); 
} 

現在服務器控制檯應用程序看起來像這樣,我們首先實現服務合同(又沒有什麼特別的存在,只是類實現接口),然後將它們全部註冊爲服務(注意在這裏不需要任何配置文件,並且可以使用Windsor提供的所有選項來更改決定什麼是服務等的方式) - 我的方案有點有限,但它給你一個想法):

namespace Services 
{ 
    public class MyService1 : IMyService1 
    { 
     public void DoSomething() 
     { 
     } 
    } 

    public class MyService2 : IMyService2 
    { 
     public void DoSomethingToo() 
     { 
     } 
    } 
} 

//... In some other namespace... 

class Program 
{ 
    // Console application main 
    static void Main() 
    { 
     // Construct the container, add the facility and then register all 
     // the types in the same namespace as the MyService1 implementation 
     // as WCF services using the name as the URL (so for example 
     // MyService1 would be http://localhost/MyServices/MyService1) and 
     // with the default interface as teh service contract 
     var container = new WindsorContainer();    
     container.AddFacility<WcfFacility>(
      f => f.CloseTimeout = TimeSpan.Zero); 
     container 
      .Register(
       AllTypes 
        .FromThisAssembly() 
        .InSameNamespaceAs<MyService1>() 
        .WithServiceDefaultInterfaces() 
        .Configure(c => 
           c.Named(c.Implementation.Name) 
            .AsWcfService(
             new DefaultServiceModel() 
              .AddEndpoints(WcfEndpoint 
                  .BoundTo(new WSHttpBinding()) 
                  .At(string.Format(
                   "http://localhost/MyServices/{0}", 
                   c.Implementation.Name) 
                  ))))); 

     // Now just wait for a Q before shutting down 
     while (Console.ReadKey().Key != ConsoleKey.Q) 
     { 
     } 
    } 
} 

這是服務器,現在如何使用這些服務?好吧,其實這是很容易的,這裏是一個客戶端控制檯應用程序(它引用只是合同類庫):

class Program 
{ 
    static void Main() 
    { 
     // Create the container, add the facilty and then use all the 
     // interfaces in the same namespace as IMyService1 in the assembly 
     // that contains the aforementioned namesapce as WCF client proxies 
     IWindsorContainer container = new WindsorContainer(); 

     container.AddFacility<WcfFacility>(
      f => f.CloseTimeout = TimeSpan.Zero); 

     container 
      .Register(
       Types 
        .FromAssemblyContaining<IMyService1>() 
        .InSameNamespaceAs<IMyService1>() 
        .Configure(
         c => c.Named(c.Implementation.Name) 
           .AsWcfClient(new DefaultClientModel 
                { 
                 Endpoint = WcfEndpoint 
                  .BoundTo(new WSHttpBinding()) 
                  .At(string.Format(
                   "http://localhost/MyServices/{0}", 
                   c.Name.Substring(1))) 
                }))); 

     // Now we just resolve them from the container and call an operation 
     // to test it - of course, now they are in the container you can get 
     // hold of them just like any other Castle registered component 
     var service1 = container.Resolve<IMyService1>(); 
     service1.DoSomething(); 

     var service2 = container.Resolve<IMyService2>(); 
     service2.DoSomethingToo(); 
    } 
} 

這就是它 - 希望這將讓你開始(我發現,試驗和使用智能感知通常把我帶到我需要去的地方)。我向你展示了服務和客戶端,但如果你願意,你可以使用其中一種。

您應該能夠看到綁定配置的位置以及我如何構建URL,因此在您的情況下,您可以輕鬆地從配置文件或任何想要執行的操作中摘取基本URL。

提最後一件事是,你就可以把它作爲一個擴展到端點添加自定義端點行爲,所以在客戶端的例子,你就會有這樣的事情:

Endpoint = WcfEndpoint 
    .BoundTo(new WSHttpBinding()) 
    .At(string.Format("http://localhost/MyServices/{0}", c.Name.Substring(1))) 
    .AddExtensions(new AuthTokenBehavior()) 
+0

這就像一個魅力,非常感謝。 – 2012-04-12 01:25:19

+0

這是幹什麼的? (f => f.CloseTimeout = TimeSpan.Zero) – 2012-04-12 01:36:28

+0

設置所有服務的默認closetimeout - 這是「TimeSpan值,它指定爲完成關閉操作提供的時間間隔。該值應大於或等於等於零,默認爲00:01:00。「 - 來自http://msdn.microsoft.com/en-us/library/ms731361.aspx。這裏還有一個很好的主題,講述了所有可能的超時:http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/84551e45-19a2-4d0d-bcc0-516a4041943d/ – kmp 2012-04-12 06:38:11