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