基于Autofac, Castle.DynamicProxy的动态WCF解决方案(原创)

本方案解决了下面3个主要的问题:

1、减少配置,为了避免每次新增service都需要去修改配置文件,包括服务器端跟各个客户端的。

2、能够使用函数重载,泛型函数,以及泛型类。

3、使项目能够快速地在wcf与直接调用dll之间切换。

整个解决方案分为四块内容:1、客户端,2、契约层,3、服务端,4、实现层

1、客户端:只能看到契约层,而看不到具体的实现;但也可以通过直接引用实现层,从而脱离wcf(需要修改工厂方法,也可以改进一下,通过配置文件来做这个事情,但这个不是本解决方案的重点,有兴趣的可以自己去实现)。

2、契约层:包含DTO对象模型跟各个服务接口

3、服务端:能看到契约层跟实现层

4、实现层:使用Autofac跟Castle.DynamicProxy进行IOC跟AOP(动态代理中的拦截器)

为解决第一个问题,早些年,已有人通过只暴露WCF的一个服务,而向该服务传递类名,函数名,参数数组来解决这一问题,但是用字符串在我看来实在是不太好,谁能保证自己在编码的时候不会把字符串给写错呢,而且万一需要更改服务名,vs的代码重构机制也处理不了字符串。所以我觉得利用接口,应该是最好的解决方案,但问题是谁又能在不知道具体的实现类的情况下,而针对接口凭空实例化出来一个对象呢。答案是有的,用Emit指令,不过Emit指令实在是有点难。此时我又想到了单元测试中常用的Rhino Mocks跟moq框架,便去查看了它们的源代码,我发现其中一个用的.net自带的真实代理(RealProxy),另外个用的是Castle.DynamicProxy,个人比较喜欢Castle.DynamicProxy,就用了它的CreateInterfaceProxyWithoutTarget,然后在自定义的拦截器中去调用实际的WCF服务,将返回回来的值设置给invocation.ReturnValue。

并且针对方法中的传引用的参数,进行了处理,使其能够对传引用的参数进行赋值。

下图为整个解决方案的结构:

测试的接口:

 1 public interface IMyTest
 2     {
 3         int Test1();
 4         void Test2();
 5         int Test3(int value);
 6         TestModel Test4(ref TestModel T);
 7         void Test5(TestModel T);
 8         void Test6(out int value);
 9         void Test7(ref int value);
10         int Test8(int value = 8);
11         int Test9(int value1 = 0, int value2 = 0);
12         int Test10(params int[] values);
13         int Test11(ref List<int> lst);
14         int Test12(TestEnumModel m);
15         TestEnumModel Test13(TestEnumModel m);
16         T Test14<T>(T m);
17         string Test14<T>(T m, int value);
18         string Test14<T>(T m, string value);
19         string Test14<T>(T m, TestModel model);
20     }
IMyTest接口
1 public interface IMyTest2<T>
2     {
3         T Test(T aa);
4     }
IMyTest2泛型接口

DTO对象:

 1 public class TestModel
 2     {
 3         public int A { get; set; }
 4     }
 5 
 6 public class TestImpModel : TestModel
 7     {
 8         public string B { get; set; }
 9     }
10 
11 public enum TestEnumModel
12     {
13         A = 0,
14         B = 1
15     }
DTO对象们

具体实现:

 1 internal class MyTest : IMyTest
 2     {
 3         public int Test1()
 4         {
 5             return 1;
 6         }
 7 
 8         public void Test2()
 9         {
10 
11         }
12 
13         public int Test3(int value)
14         {
15             return value + 1;
16         }
17 
18         public TestModel Test4(ref TestModel T)
19         {
20             T.A = T.A + 1;
21             return T;
22         }
23 
24         public void Test5(TestModel T)
25         {
26             T.A = T.A + 1;
27         }
28 
29         public void Test6(out int value)
30         {
31             value = 3;
32         }
33 
34         public void Test7(ref int value)
35         {
36             value++;
37         }
38 
39 
40         public int Test8(int value = 8)
41         {
42             return value;
43         }
44 
45 
46         public int Test9(int value1 = 0, int value2 = 0)
47         {
48             return value1 + value2;
49         }
50 
51 
52         public int Test10(params int[] values)
53         {
54             return values.Sum();
55         }
56 
57 
58         public int Test11(ref List<int> lst)
59         {
60             lst.Add(3);
61             return lst.Sum();
62         }
63 
64         public int Test12(TestEnumModel m)
65         {
66             return (int)m;
67         }
68 
69         public TestEnumModel Test13(TestEnumModel m)
70         {
71             return m;
72         }
73 
74         public T Test14<T>(T m)
75         {
76             return m;
77         }
78 
79         public string Test14<T>(T m, int value)
80         {
81             return m.ToString() + value.ToString();
82         }
83 
84         public string Test14<T>(T m, string value)
85         {
86             return m.ToString() + value;
87         }
88 
89         public string Test14<T>(T m, TestModel model)
90         {
91             model.A += 1;
92             return m.ToString() + model.A.ToString();
93         }
94     }
实现了IMyTest的MyTest类
1 internal class MyTest2<T> : IMyTest2<T>
2     {
3         public T Test(T aa)
4         {
5             return aa;
6         }
7     }
实现了IMyTest2的MyTest2泛型类

测试用例:

  1 [TestMethod]
  2         public void TestMethod1()
  3         {
  4             Assert.AreEqual(1, MyCreator.Create<IMyTest>().Test1());
  5         }
  6 
  7         [TestMethod]
  8         public void TestMethod2()
  9         {
 10             MyCreator.Create<IMyTest>().Test2();
 11         }
 12 
 13         [TestMethod]
 14         public void TestMethod3()
 15         {
 16             Assert.AreEqual(4, MyCreator.Create<IMyTest>().Test3(3));
 17             Assert.AreEqual(3, MyCreator.Create<IMyTest>().Test3(2));
 18         }
 19 
 20         [TestMethod]
 21         public void TestMethod4()
 22         {
 23             var tm = new TestModel() { A = 2 };
 24             var t = MyCreator.Create<IMyTest>().Test4(ref tm);
 25             Assert.AreEqual(3, t.A);
 26             Assert.AreEqual(3, tm.A);
 27         }
 28 
 29         [TestMethod]
 30         public void TestMethod5()
 31         {
 32             var t = new TestModel() { A = 2 };
 33             MyCreator.Create<IMyTest>().Test5(t);
 34             Assert.AreEqual(2, t.A);
 35         }
 36 
 37         [TestMethod]
 38         public void TestMethod6()
 39         {
 40             int i = 0;
 41             MyCreator.Create<IMyTest>().Test6(out i);
 42             Assert.AreEqual(3, i);
 43         }
 44 
 45         [TestMethod]
 46         public void TestMethod7()
 47         {
 48             int i = 0;
 49             MyCreator.Create<IMyTest>().Test7(ref i);
 50             Assert.AreEqual(1, i);
 51         }
 52 
 53         [TestMethod]
 54         public void TestMethod8()
 55         {
 56             Assert.AreEqual(8, MyCreator.Create<IMyTest>().Test8());
 57         }
 58 
 59         [TestMethod]
 60         public void TestMethod9()
 61         {
 62             Assert.AreEqual(12, MyCreator.Create<IMyTest>().Test9(value2: 12));
 63         }
 64 
 65         [TestMethod]
 66         public void TestMethod10()
 67         {
 68             Assert.AreEqual(3, MyCreator.Create<IMyTest>().Test10(1, 2));
 69         }
 70 
 71         [TestMethod]
 72         public void TestMethod11()
 73         {
 74             List<int> lst = new List<int>();
 75             Assert.AreEqual(3, MyCreator.Create<IMyTest>().Test11(ref lst));
 76             Assert.AreEqual(1, lst.Count);
 77             Assert.AreEqual(3, lst[0]);
 78         }
 79 
 80         [TestMethod]
 81         public void TestMethod12()
 82         {
 83             Assert.AreEqual(1, MyCreator.Create<IMyTest>().Test12(TestEnumModel.B));
 84         }
 85 
 86         [TestMethod]
 87         public void TestMethod13()
 88         {
 89             Assert.AreEqual(TestEnumModel.B, MyCreator.Create<IMyTest>().Test13(TestEnumModel.B));
 90         }
 91 
 92         [TestMethod]
 93         public void TestMethod14()
 94         {
 95             Assert.AreEqual(TestEnumModel.B, MyCreator.Create<IMyTest>().Test14(TestEnumModel.B));
 96         }
 97 
 98         [TestMethod]
 99         public void TestMethod15()
100         {
101             Assert.AreEqual("B123", MyCreator.Create<IMyTest>().Test14(TestEnumModel.B, 123));
102         }
103 
104         [TestMethod]
105         public void TestMethod16()
106         {
107             Assert.AreEqual("Baaaaa", MyCreator.Create<IMyTest>().Test14(TestEnumModel.B, "aaaaa"));
108         }
109 
110         [TestMethod]
111         public void TestMethod17()
112         {
113             TestImpModel m = new TestImpModel() { A = 1, B = "3" };
114             Assert.AreEqual("B2", MyCreator.Create<IMyTest>().Test14(TestEnumModel.B, m));
115             Assert.AreEqual(1, m.A);
116             Assert.AreEqual("3", m.B);
117         }
118 
119         [TestMethod]
120         public void TestMethod18()
121         {
122             TestImpModel m = new TestImpModel() { A = 1, B = "3" };
123             var n = MyCreator.Create<IMyTest2<TestImpModel>>().Test(m);
124             Assert.AreEqual(1, n.A);
125             Assert.AreEqual("3", n.B);
126         }
18个简单的测试用例

项目源代码:DynamicWCF.rar

原文地址:https://www.cnblogs.com/nickppa/p/4562347.html