使用Castle Windsor WcfFacility创建客户端端点 [英] Using Castle Windsor WcfFacility to create client endpoints

查看:86
本文介绍了使用Castle Windsor WcfFacility创建客户端端点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了三个程序集.一个网站,一个WCF服务和一个合同程序集,其中包含该服务实现的接口.我想使用Castle Windsor在客户端(网站)上为我创建服务,这样我就不必为要使用的每种服务在网站的web.config中拥有一个终结点.

I have created three assemblies. A web site, a WCF service and a contracts assembly that holds the interfaces that the services implement. I would like to use Castle Windsor to create the services for me on the client (website) so that I do not have to have an endpoint in the web.config of the web site for each service that I wish to use.

我想看看合同程序集,并在命名空间中获取所有服务接口.现在,在容器中注册组件时,对于每项服务,我都有类似以下内容.

I would like to look at the contract assembly and get all the service interfaces in a namespace. Right now for every service I have something like the following when registering the components with the container.

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中,我有设置代码.

and in my web.config I have the setup code.

  <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都一样,它们也必须设置每个端点的地址.

I end up with multiple service endpoints that all look almost exactly the same and when we deploy onto clients machines they have to set the address of every endpoint even though the base url is the same for every one.

我想在我的web.config文件中有一个通过代码获取的基本URL,然后使用对合同程序集的反射将服务注册到容器中.我确实需要上述配置文件中的特殊端点行为.

I would like to have a base url in my web.config that is grabbed through code and then have the services registered with the container using reflection on the contracts assembly. I do need the specialised endpoint behaviour that is in the above config file.

我从哪里开始? WcfFacility看起来不错,但是doco有点缺乏...

Where so I start? the WcfFacility looks great but the doco is a bit lacking...

推荐答案

我同意缺少wcf工具的文档,这令人遗憾,因为它是一个非常好的工具,如果人们不这样做,那将是真正的耻辱使用它是因为他们无法入门,所以让我看看是否可以帮助您...

I agree the docs for the wcf facility are lacking and that is sad because it is a really great tool and it would be a real shame if people didn't use it because they could not get started, so let me see if I can help you out a little bit if I can...

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

Let's create a three project application that has:

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

这个想法是,我们希望能够在注册服务时使用服务名称并共享基本URL(我想这就是您要的内容,如果没有,希望您可以从此处进行推断).因此,首先,共享合同中仅包含此内容(没有特殊的常规WCF票价):

The idea is that we want to be able to use the service names when we register the services and to share a base URL (I think that is what you were asking and if not, hopefully you can extrapolate from here). So, firstly, the shared contracts simply has this in it (nothing special, normal WCF fare):

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

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

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

Now the server console application looks like this, we firstly implement the service contracts (again nothing special there, just classes implementing interfaces) and then just register them all as services (notice no need for any configuration file here and you can change the way you decide what are services etc using all the options that Windsor gives you - my scheme is a bit limited but it gives you an idea):

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)
        {
        }
    }
}

那是服务器,现在如何使用这些服务?好吧,实际上这很容易,这是一个客户端控制台应用程序(它仅引用合同类库):

And that is the server, now how to consume these services? Well, actually that is quite easy, here is a client console application (it references just the contracts class library):

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

就是这样-希望这可以帮助您入门(我发现尝试并使用智能感知通常可以帮助我到达需要去的地方).我向您展示了服务端和客户端,但是如果您愿意,可以只使用其中之一.

That's it - hopefully this will get you started (I find that experimenting and using the intellisense usually gets me where I need to go). I showed you both the service and client sides but you can just use one or the other if you prefer.

您应该能够看到绑定的配置位置以及构建URL的方式,因此,在您的情况下,您可以轻松地从配置文件中提取基本URL或进行任何操作.

You should be able to see where the binding is configured and how I have gone about constructing the URLs so in your case you could easily just pluck your base URL from a configuration file or whatever you want to do.

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

One last thing to mention is that you can add your custom endpoint behaviour by adding it as an extension to the endpoint, so in the client example you would have something like this:

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

这篇关于使用Castle Windsor WcfFacility创建客户端端点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆