6

Я создал три сборки. Веб-сайт, служба WCF и сборка контрактов, которая содержит интерфейсы, которые реализуют сервисы. Я хотел бы использовать Castle Windsor для создания сервисов для меня на клиенте (веб-сайте), так что мне не нужно иметь конечную точку в web.config веб-сайта для каждой службы, которую я хочу использовать.Использование Castle Windsor WcfУстановка для создания конечных точек клиента

Я хотел бы посмотреть контрактную сборку и получить все служебные интерфейсы в пространстве имен. Прямо сейчас для каждой службы у меня есть что-то вроде следующего при регистрации компонентов с контейнером.

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 является одинаковым для всех.

Я хотел бы иметь базовый url в моем web.config, который захватывается через код, а затем службы, зарегистрированные в контейнере, используя отражение на сборке контрактов. Мне нужно специализированное поведение конечных точек, которое находится в приведенном выше файле конфигурации.

Где я начинаю? WcfFacility выглядит великолепно, но doco немного не хватает ...

ответ

12

Я согласен, что документы для объекта wcf отсутствуют, и это печально, потому что это действительно отличный инструмент, и было бы очень обидно, если бы люди не " т использовать его, потому что они не могли начать, поэтому позвольте мне увидеть, если я могу помочь вам немного, если я могу ...

Давайте создадим приложение на три проекта, который имеет:

  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(); 
    } 
} 

Вот это - надеюсь, это поможет вам начать работу (я считаю, что экспериментировать и с помощью IntelliSense обычно получает меня туда, куда мне нужно идти).Я показал вам как сторону обслуживания, так и клиентов, но вы можете просто использовать то или другое, если хотите.

Вы должны уметь видеть, где привязка привязана и как я начал строить 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», которое задает интервал времени, предоставляемый для завершения операции закрытия. Это значение должно быть больше или равно равным нулю. Значение по умолчанию - 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

Смежные вопросы