gpt4 book ai didi

wcf - 使用 CaSTLe Windsor WcfFacility 创建客户端端点

转载 作者:行者123 更新时间:2023-12-04 10:27:59 24 4
gpt4 key购买 nike

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

我想查看契约(Contract)程序集并获取命名空间中的所有服务接口(interface)。现在,在向容器注册组件时,对于每项服务,我都有类似以下内容。

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 有点缺乏......

最佳答案

我同意缺少 wcf 工具的文档,这很可悲,因为它是一个非常棒的工具,如果人们因为无法开始而不使用它,那将是一个真正的耻辱,所以让我看看我是否可以提供帮助如果可以的话,你出去一点...

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

  • 共享合约的类库
  • 充当服务器的控制台应用程序
  • 充当客户端的控制台应用程序

  • 我们的想法是,我们希望能够在注册服务时使用服务名称并共享一个基本 URL(我认为这就是您所要求的,如果不是,希望您可以从这里推断)。因此,首先,共享契约(Contract)中包含以下内容(没什么特别的,正常的 WCF 票价):
    [ServiceContract]
    public interface IMyService1
    {
    [OperationContract]
    void DoSomething();
    }

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

    现在服务器控制台应用程序看起来像这样,我们首先实现服务契约(同样没有什么特别之处,只是实现接口(interface)的类)然后将它们全部注册为服务(注意这里不需要任何配置文件,您可以更改方式使用 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)
    {
    }
    }
    }

    那就是服务器,现在如何消费这些服务?好吧,实际上这很容易,这是一个客户端控制台应用程序(它只引用了contracts 类库):
    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();
    }
    }

    就是这样——希望这能让你开始(我发现实验和使用智能感知通常能让我到达我需要去的地方)。我向您展示了服务和客户端,但如果您愿意,您可以只使用其中之一。

    您应该能够看到绑定(bind)的配置位置以及我如何构建 URL,因此在您的情况下,您可以轻松地从配置文件或任何您想做的事情中提取基本 URL。

    最后要提到的一件事是,您可以通过将自定义端点行为添加为端点的扩展来添加它,因此在客户端示例中,您将拥有如下内容:
    Endpoint = WcfEndpoint
    .BoundTo(new WSHttpBinding())
    .At(string.Format("http://localhost/MyServices/{0}", c.Name.Substring(1)))
    .AddExtensions(new AuthTokenBehavior())

    关于wcf - 使用 CaSTLe Windsor WcfFacility 创建客户端端点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10085172/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com