基於Autofac, Castle.DynamicProxy的動態WCF解決方案(原創)

本方案解決了下面3個主要的問題:數組

一、減小配置,爲了不每次新增service都須要去修改配置文件,包括服務器端跟各個客戶端的。服務器

二、可以使用函數重載,泛型函數,以及泛型類。框架

三、使項目可以快速地在wcf與直接調用dll之間切換。ide

 

整個解決方案分爲四塊內容:一、客戶端,二、契約層,三、服務端,四、實現層函數

一、客戶端:只能看到契約層,而看不到具體的實現;但也能夠經過直接引用實現層,從而脫離wcf(須要修改工廠方法,也能夠改進一下,經過配置文件來作這個事情,但這個不是本解決方案的重點,有興趣的能夠本身去實現)。單元測試

二、契約層:包含DTO對象模型跟各個服務接口測試

三、服務端:能看到契約層跟實現層編碼

四、實現層:使用Autofac跟Castle.DynamicProxy進行IOC跟AOP(動態代理中的攔截器)spa

 

爲解決第一個問題,早些年,已有人經過只暴露WCF的一個服務,而向該服務傳遞類名,函數名,參數數組來解決這一問題,可是用字符串在我看來實在是不太好,誰能保證本身在編碼的時候不會把字符串給寫錯呢,並且萬一須要更改服務名,vs的代碼重構機制也處理不了字符串。因此我以爲利用接口,應該是最好的解決方案,但問題是誰又能在不知道具體的實現類的狀況下,而針對接口憑空實例化出來一個對象呢。答案是有的,用Emit指令,不過Emit指令實在是有點難。此時我又想到了單元測試中經常使用的Rhino Mocks跟moq框架,便去查看了它們的源代碼,我發現其中一個用的.net自帶的真實代理(RealProxy),另外個用的是Castle.DynamicProxy,我的比較喜歡Castle.DynamicProxy,就用了它的CreateInterfaceProxyWithoutTarget,而後在自定義的攔截器中去調用實際的WCF服務,將返回回來的值設置給invocation.ReturnValue。.net

而且針對方法中的傳引用的參數,進行了處理,使其可以對傳引用的參數進行賦值。

下圖爲整個解決方案的結構:

 

測試的接口:

 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

相關文章
相關標籤/搜索