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的配置文件(正式的运行环境通常还是需要配置在灵活性方面的优势)。

posted on 2010-05-14 15:13  Zhenway  阅读(665)  评论(0编辑  收藏  举报