zoukankan      html  css  js  c++  java
  • 在3.5下实现无配置WCF服务

        WCF在不断的进步,在4.0下可以很简单的实现无配置WCF,从此不再为哪大段大段的配置而感到头痛了。

        但是,现实是残酷的,项目的.net框架版本不是说变就变的。不过,对于会写代码的人来说,总有办法能绕过这些杂七杂八的麻烦事情。

        之前的一片文章中已经写了无配置客户端如何实现,但是里面的服务端还是需要配置的,这样还是有少许的不便。所以,今天再来一个完全不用配置文件的WCF测试全套方案不漏——WCF无配置Service端(3.5框架)

        首先,来想一下,WCF需要配置的罪魁祸首是谁?微软,呵呵,确实没错,但是,再具体一点——ServiceHost类。

        就是它要去读取配置,所以,要想实现无配置的WCF服务端,必须从这个类开刀。于是需要修改一下这个类型的某些行为:

       1:      public class SimpleServiceHost
       2:          : ServiceHost
       3:      {
       4:   
       5:          public Uri Uri { get; set; }
       6:          public Binding Binding { get; private set; }
       7:   
       8:          public SimpleServiceHost(Type serviceType,
       9:              Binding binding, Uri uri)
      10:          {
      11:              if (uri == null)
      12:                  throw new ArgumentNullException("uri");
      13:              if (binding == null)
      14:                  throw new ArgumentNullException("binding");
      15:              Uri = uri;
      16:              Binding = binding;
      17:              InitializeDescription(serviceType, new UriSchemeKeyedCollection(uri));
      18:          }
      19:   
      20:          public SimpleServiceHost(object singletonInstance,
      21:              Binding binding, Uri uri)
      22:          {
      23:              if (singletonInstance == null)
      24:                  throw new ArgumentNullException("singletonInstance");
      25:              if (uri == null)
      26:                  throw new ArgumentNullException("uri");
      27:              if (binding == null)
      28:                  throw new ArgumentNullException("binding");
      29:              Uri = uri;
      30:              Binding = binding;
      31:              InitializeDescription(singletonInstance, new UriSchemeKeyedCollection(uri));
      32:          }
      33:   
      34:          protected override ServiceDescription CreateDescription(
      35:              out IDictionary<string, ContractDescription> implementedContracts)
      36:          {
      37:              var result = base.CreateDescription(out implementedContracts);
      38:              foreach (var contract in implementedContracts.Values)
      39:              {
      40:                  var endpoint = new ServiceEndpoint(contract, Binding, new EndpointAddress(Uri.ToString()));
      41:                  endpoint.Name = Binding.Name + "_" + contract.Name;
      42:                  result.Endpoints.Add(endpoint);
      43:              }
      44:              return result;
      45:          }
      46:   
      47:      }

        这个SimpleServiceHost直接继承ServiceHost,然后修改了CreateDescription方法,为契约们增加终结点。

        看到这里,一定会想然后哪?

        不幸的是,这些就是全部的代码了,后面的都是测试代码了,是不是感觉太简单了,就像被忽悠了。是不是被忽悠就直接看测试吧(别忘了上一片文章里面的两个扩展方法):

       1:  [TestMethod]
       2:  public void TestHelloService()
       3:  {
       4:      var uri = new Uri("net.tcp://127.0.0.1:2323/Console/");
       5:      var binding = new NetTcpBinding();
       6:      new SimpleServiceHost(typeof(HelloService), binding, uri).RunWcfService(
       7:          () => uri.InvokeWcfClient<IHelloService>(binding,
       8:              c => Assert.AreEqual("Hello world!", c.Hello("world"))));
       9:  }
      10:   
      11:  [ServiceContract]
      12:  public interface IHelloService
      13:  {
      14:      [OperationContract]
      15:      string Hello(string name);
      16:  }
      17:   
      18:  public class HelloService
      19:      : IHelloService
      20:  {
      21:      public string Hello(string name)
      22:      {
      23:          return "Hello " + name + "!";
      24:      }
      25:  }

        只要这些测试代码,我们的测试就可以跑了。

        如果是实现类实现了多个服务契约会怎么样哪?

       1:  [TestMethod]
       2:  public void TestMultiService()
       3:  {
       4:      var uri = new Uri("net.tcp://127.0.0.1:2323/Multi/");
       5:      var binding = new NetTcpBinding();
       6:      new SimpleServiceHost(typeof(MultiService), binding, uri).RunWcfService(
       7:          () =>
       8:          {
       9:              uri.InvokeWcfClient<IHelloService>(binding,
      10:                  c => Assert.AreEqual("Hello world!", c.Hello("world")));
      11:              uri.InvokeWcfClient<IEchoService>(binding,
      12:                  c => Assert.AreEqual("abc", c.Echo("abc")));
      13:          });
      14:  }
      15:   
      16:  [ServiceContract]
      17:  public interface IEchoService
      18:  {
      19:      [OperationContract]
      20:      string Echo(string message);
      21:  }
      22:   
      23:  public class MultiService
      24:      : IHelloService, IEchoService
      25:  {
      26:      public string Hello(string name)
      27:      {
      28:          return "Hello " + name + "!";
      29:      }
      30:   
      31:      public string Echo(string message)
      32:      {
      33:          return message;
      34:      }
      35:  }

         IHelloService的契约不变,再加个IEchoService,在测试用例中同时测试这两个客户端,可以发现依然正常。

        有了这个类,在单元测试中,就完全可以抛弃WCF的配置文件(正式的运行环境通常还是需要配置在灵活性方面的优势)。

  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/vwxyzh/p/1735497.html
Copyright © 2011-2022 走看看