首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Castle Windsor WcfFacility创建客户端端点

使用Castle Windsor WcfFacility创建客户端端点
EN

Stack Overflow用户
提问于 2012-04-10 16:01:14
回答 1查看 8.6K关注 0票数 7

我已经创建了三个程序集。网站、WCF服务和包含服务实现的接口的协定程序集。我想使用Castle Windsor在客户端(网站)上为我创建服务,这样我就不必在网站的web.config中为我希望使用的每个服务创建端点。

我希望查看协定程序集,并获取名称空间中的所有服务接口。现在,对于每个服务,在向容器注册组件时,我都有类似以下内容。

代码语言:javascript
运行
复制
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中,我有设置代码。

代码语言:javascript
运行
复制
  <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,然后使用contracts程序集上的反射将服务注册到容器中。我确实需要上面配置文件中的特殊端点行为。

那么我从哪里开始呢?WcfFacility看起来很棒,但doco有点欠缺...

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-04-11 14:34:07

我同意wcf工具的文档是缺乏的,这是可悲的,因为它是一个真正伟大的工具,如果人们因为无法入门而不使用它,那将是一个真正的耻辱,所以让我看看如果我能帮你一点忙…

让我们创建一个包含三个项目的应用程序,该应用程序具有:

  1. 用于共享合同的类库
  2. 用作服务器的控制台应用程序
  3. 用作客户端

的控制台应用程序

我们的想法是,我们希望能够在注册服务时使用服务名称,并共享一个基本URL (我认为这就是您所问的,如果不是,希望您可以从这里推断出来)。因此,首先,共享合同中只包含以下内容(没有什么特殊的,正常的WCF费用):

代码语言:javascript
运行
复制
[ServiceContract]
public interface IMyService1
{
    [OperationContract]
    void DoSomething();
}

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

现在服务器控制台应用程序看起来像这样,我们首先实现服务契约(同样没有什么特别的,只是实现接口的类),然后将它们全部注册为服务(注意,这里不需要任何配置文件,您可以使用Windsor提供的所有选项来更改决定服务等的方式-我的方案有点有限,但它给了您一个想法):

代码语言:javascript
运行
复制
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)
        {
        }
    }
}

那就是服务器,现在该如何使用这些服务呢?实际上这很简单,下面是一个客户端控制台应用程序(它只引用了contracts类库):

代码语言:javascript
运行
复制
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。

最后要提到的是,您可以通过将自定义端点行为添加为端点的扩展来添加自定义端点行为,因此在客户端示例中,您将拥有如下内容:

代码语言:javascript
运行
复制
Endpoint = WcfEndpoint
    .BoundTo(new WSHttpBinding())
    .At(string.Format("http://localhost/MyServices/{0}", c.Name.Substring(1)))
    .AddExtensions(new AuthTokenBehavior())
票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10085172

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档