6

세 개의 어셈블리를 만들었습니다. 웹 사이트, WCF 서비스 및 서비스가 구현하는 인터페이스를 보유하는 계약 어셈블리. Castle Windsor를 사용하여 클라이언트 (웹 사이트)에서 나를 위해 서비스를 만들고 싶습니다. 사용하려는 각 서비스에 대한 웹 사이트의 web.config에 끝점이 없어도됩니다.Castle Windsor 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는 좋아 보이지만 도코는 조금 부족합니다 ...

답변

12

저는 wcf 기능에 대한 문서가 부족하고 그것이 정말 좋은 도구이기 때문에 슬프고 사람들이 '

  1. 하는 클래스 : t은

    이의가있는 세 가지 프로젝트 응용 프로그램을 만들어 보자 ... 그들이 시작하지 못했기 때문에 그것을 사용하기 때문에 내가 할 수 있다면 내가 조금 당신을 도울 수 있다면 나를 보자 공유 계약 용 라이브러리
  2. 서버 역할을하는 콘솔 응용 프로그램
  3. 클라이언트

아이디어 역할을하는 콘솔 응용 프로그램은 우리가 서비스를 등록 할 때 서비스 이름을 사용하고 기본 URL을 공유 할 수 있기를 원하는 것입니다 (나는 당신이 요구 한 것을 생각 그리고 그렇지 않다면, 여기에서 추정 할 수 있습니다.)

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

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

지금 서버 콘솔 응용 프로그램은 다음과 같습니다

, 우리는 첫째로 그냥 거기 서비스 계약 특별 (다시 아무것도 구현하지 : 그래서, 첫째, 공유 계약 간단하게 (아무 특별 정상 WCF 요금) 안에이있다 인터페이스를 구현하는 클래스)를 선택하고 서비스로 등록하면됩니다. (여기에 어떤 구성 파일도 필요하지 않으며 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

유사한 작동 매력, 대단히 감사합니다. –

+0

이것은 무엇을합니까? (f => f.CloseTimeout = TimeSpan.Zero) –

+0

모든 서비스에 대한 기본 클로우 타임 아웃을 설정합니다. "닫기 작업이 완료 될 때까지 제공되는 시간 간격을 지정하는 TimeSpan 값입니다. 0과 같습니다. 기본값은 00:01:00입니다. " - http://msdn.microsoft.com/ko-kr/library/ms731361.aspx. 또한 가능한 모든 시간 초과에 대해 이야기하는 좋은 스레드가 있습니다. http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/84551e45-19a2-4d0d-bcc0-516a4041943d/ – kmp

관련 문제