C#程式設計模式之擴充指令
前言
根據上一篇的指令模式和在工作中遇到的一些實際情況,有了本篇文章,時時都是學習的一個過程,會在這個過程中發現許多好的模式或者是一種開發方式,今天寫出來的就是我工作中常用到的,自己感覺這種方式很優雅很漂亮,就自己試着實作了一下,可能原架構中不是這樣的,有許多不足之處還請大家指點。
需求
我還不清楚這種方式是模式還是架構開發中用到的技術,我暫且叫它為指令控制器吧。
指令控制器的主要功能就是擷取使用者提供的指令,然後來執行指令。 在這裡我把要執行的“指令”設計成一個函數,會對應着一個String類型的指令字元串,并且指令控制器是允許擴充的。
實作
首先我定義了一個屬性類,用于在擴充的指令類、或者指令函數上,隻有一個CommandName屬性,作用于指令函數上的話,則代表指令名稱,如果是作用于類上面的話就代表指令類别的名稱,隻是考慮可以作為一個分類,這部分在後面有講到,可以自定義實作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<code>1 </code><code>/// <summary></code>
<code>2 </code><code>/// 指令所用代碼屬性類</code>
<code>3 </code><code>/// </summary></code>
<code>4 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = </code><code>false</code><code>, Inherited = </code><code>true</code><code>)]</code>
<code>5 </code><code>public</code> <code>class</code> <code>CommandAttribute : Attribute</code>
<code>6 {</code>
<code>7 </code><code>private</code> <code>string</code> <code>commandName = </code><code>null</code><code>;</code>
<code>8</code>
<code>9 </code><code>public</code> <code>string</code> <code>CommandName</code>
<code>10 {</code>
<code>11 </code><code>get</code> <code>{ </code><code>return</code> <code>commandName; }</code>
<code>12 </code><code>set</code> <code>{ commandName = value; }</code>
<code>13 }</code>
<code>14</code>
<code>15 </code><code>public</code> <code>CommandAttribute(</code><code>string</code> <code>CommandName)</code>
<code>16 {</code>
<code>17 commandName = CommandName;</code>
<code>18 }</code>
<code>19 }</code>
有了這個屬性類了,我們就要把它用起來,定義一些後面要用到的指令示例類,
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<code>2 </code><code>/// 示例:指令類以及指令函數,亦可當作為擴充</code>
<code>4 [Command(</code><code>"Test"</code><code>)]</code>
<code>5 </code><code>public</code> <code>class</code> <code>CommandTest : CommandMethod</code>
<code>7 [Command(</code><code>"MyCommandone"</code><code>)]</code>
<code>8 </code><code>public</code> <code>object</code> <code>test(ICommandParameter commandparameter)</code>
<code>9 {</code>
<code>10 </code><code>return</code> <code>null</code><code>;</code>
<code>11 }</code>
<code>12</code>
<code>13 [Command(</code><code>"MyCommandone1"</code><code>)]</code>
<code>14 </code><code>public</code> <code>object</code> <code>test1(ICommandParameter commandparameter)</code>
<code>15 {</code>
<code>16 </code><code>return</code> <code>null</code><code>;</code>
<code>17 }</code>
<code>18</code>
<code>19 [Command(</code><code>"MyCommandone2"</code><code>)]</code>
<code>20 </code><code>public</code> <code>object</code> <code>test2(ICommandParameter commandparameter)</code>
<code>21 {</code>
<code>22 </code><code>return</code> <code>null</code><code>;</code>
<code>23 }</code>
<code>24</code>
<code>25</code>
<code>26 [Command(</code><code>"MyCommandone3"</code><code>)]</code>
<code>27 </code><code>public</code> <code>object</code> <code>test3(ICommandParameter commandparameter)</code>
<code>28 {</code>
<code>29 </code><code>return</code> <code>null</code><code>;</code>
<code>30 }</code>
<code>31</code>
<code>32 [Command(</code><code>"MyCommandone4"</code><code>)]</code>
<code>33 </code><code>public</code> <code>object</code> <code>test4(ICommandParameter commandparameter)</code>
<code>34 {</code>
<code>35 </code><code>return</code> <code>null</code><code>;</code>
<code>36 }</code>
<code>37 }</code>
上面的示例代碼中可以看到CommandTest類繼承自CommandMethod類,而類裡面的一些函數的簽名也是一樣的,函數參數都為ICommandParameter接口類型,這就是擴充指令方法時要遵循的一些規範,定義的規範:
<code>2 </code><code>/// 擴充指令函數的參數規範</code>
<code>4 </code><code>public</code> <code>interface</code> <code>ICommandParameter</code>
<code>5 {</code>
<code>6</code>
<code>7 }</code>
<code>9 </code><code>/// <summary></code>
<code>10 </code><code>/// 擴充指令方法類基類</code>
<code>11 </code><code>/// </summary></code>
<code>12 </code><code>public</code> <code>class</code> <code>CommandMethod</code>
<code>13 {</code>
<code>15 }</code>
需要實作什麼都是可以自定義,比如說可以在ICommandParameter接口中定義個object類型的名稱為ContainerObject的屬性,意思就是容器屬性,可以在後面調用指令時,傳入執行個體參數時設定容器屬性的值,可以設定為任何你想設定的值到裡面,然後再在指令函數裡使用它,也可以根據抽象定義實作一個參數上下文對象專門用于處理擴充指令的,看需要自定義吧。
然後就是書寫一個指令控制器的代碼了,它呢主要負責把用戶端注冊進來的類型做一些處理,比如說 判斷類型、反射類型擷取函數指令以及函數資訊、把指令函數轉換成委托、維護指令清單等等一些簡單的功能,還用到了一個CommandMethodActionDelegate類型的委托:
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<code>1 </code><code>public</code> <code>delegate</code> <code>object</code> <code>CommandMethodActionDelegate(ICommandParameter commandParameter);</code>
<code>2</code>
<code>3 </code><code>public</code> <code>class</code> <code>CommandController</code>
<code>4 {</code>
<code>5 </code><code>private</code> <code>static</code> <code>CommandController _Instance = </code><code>null</code><code>;</code>
<code>7 </code><code>public</code> <code>static</code> <code>CommandController Instance</code>
<code>8 {</code>
<code>9 </code><code>get</code>
<code>10 {</code>
<code>11 </code><code>if</code> <code>(_Instance == </code><code>null</code><code>)</code>
<code>12 {</code>
<code>13 _Instance = </code><code>new</code> <code>CommandController(HostDevelopment.Instance);</code>
<code>14 }</code>
<code>15 </code><code>return</code> <code>_Instance;</code>
<code>16 }</code>
<code>19 </code><code>private</code> <code>HostDevelopment _CommandDevelopment = HostDevelopment.Instance;</code>
<code>20</code>
<code>21 </code><code>public</code> <code>CommandController(HostDevelopment commandDevelopment)</code>
<code>22 {</code>
<code>23 _CommandDevelopment = commandDevelopment;</code>
<code>24 }</code>
<code>26 </code><code>private</code> <code>Dictionary<</code><code>string</code><code>, CommandMethodActionDelegate> commandlist = </code><code>new</code> <code>Dictionary<</code><code>string</code><code>, CommandMethodActionDelegate>();</code>
<code>27</code>
<code>28</code>
<code>29 </code><code>private</code> <code>List<</code><code>string</code><code>> _commandNames = </code><code>null</code><code>;</code>
<code>30 </code><code>/// <summary></code>
<code>31 </code><code>/// 指令名稱集合</code>
<code>32 </code><code>/// </summary></code>
<code>33 </code><code>public</code> <code>List<</code><code>string</code><code>> CommandNames</code>
<code>35 </code><code>get</code>
<code>36 {</code>
<code>37 </code><code>if</code> <code>(_commandNames == </code><code>null</code><code>)</code>
<code>38 {</code>
<code>39 GetCommandNames();</code>
<code>40 }</code>
<code>41 </code><code>return</code> <code>_commandNames;</code>
<code>42 }</code>
<code>43 }</code>
<code>44</code>
<code>45 </code><code>private</code> <code>void</code> <code>GetCommandNames()</code>
<code>46 {</code>
<code>47</code>
<code>48 </code><code>if</code> <code>(commandlist.Count > 0)</code>
<code>49 {</code>
<code>50 </code><code>if</code> <code>(_commandNames == </code><code>null</code><code>)</code>
<code>51 {</code>
<code>52 _commandNames = </code><code>new</code> <code>List<</code><code>string</code><code>>();</code>
<code>53 }</code>
<code>54 </code><code>foreach</code> <code>(</code><code>string</code> <code>name </code><code>in</code> <code>commandlist.Keys)</code>
<code>55 {</code>
<code>56 _commandNames.Add(name);</code>
<code>57 }</code>
<code>58 }</code>
<code>59 }</code>
<code>60</code>
<code>61 </code><code>public</code> <code>bool</code> <code>RegisterCommand(</code><code>object</code> <code>instance)</code>
<code>62 {</code>
<code>63 Type t = instance.GetType();</code>
<code>64 CommandAttribute cmdatt = (CommandAttribute)Attribute.GetCustomAttribute(t, </code><code>typeof</code><code>(CommandAttribute), </code><code>false</code><code>);</code>
<code>65 </code><code>if</code> <code>(cmdatt != </code><code>null</code><code>)</code>
<code>66 {</code>
<code>67 AddCommandToModel(instance);</code>
<code>68 </code><code>return</code> <code>true</code><code>;</code>
<code>69 }</code>
<code>70 </code><code>else</code> <code>{ </code><code>return</code> <code>false</code><code>; }</code>
<code>71 }</code>
<code>72</code>
<code>73 </code><code>private</code> <code>void</code> <code>AddCommandToModel(</code><code>object</code> <code>instance)</code>
<code>74 {</code>
<code>75 Type t = instance.GetType();</code>
<code>76 MethodInfo[] methods = t.GetMethods();</code>
<code>77 </code><code>foreach</code> <code>(MethodInfo methodinfo </code><code>in</code> <code>methods)</code>
<code>78 {</code>
<code>79 CommandAttribute cmdatt = (CommandAttribute)Attribute.GetCustomAttribute(methodinfo, </code><code>typeof</code><code>(CommandAttribute), </code><code>false</code><code>);</code>
<code>80 </code><code>if</code> <code>(cmdatt != </code><code>null</code><code>)</code>
<code>81 {</code>
<code>82</code>
<code>83 CommandMethodActionDelegate commanddelegate = (CommandMethodActionDelegate)Delegate.CreateDelegate(</code><code>typeof</code><code>(CommandMethodActionDelegate), instance, methodinfo.Name);</code>
<code>84 commandlist.Add(cmdatt.CommandName, commanddelegate);</code>
<code>85 }</code>
<code>86</code>
<code>87 }</code>
<code>88 }</code>
<code>89</code>
<code>90</code>
<code>91 </code><code>internal</code> <code>object</code> <code>Execute(</code><code>string</code> <code>commandName, ICommandParameter commandParameter)</code>
<code>92 {</code>
<code>93 </code><code>if</code> <code>(commandName == </code><code>null</code><code>)</code>
<code>94 {</code>
<code>95 </code><code>throw</code> <code>new</code> <code>ArgumentNullException(</code><code>"commandName"</code><code>);</code>
<code>96 }</code>
<code>97 </code><code>if</code> <code>(!commandlist.ContainsKey(commandName))</code>
<code>98 {</code>
<code>99 </code><code>return</code> <code>new</code> <code>ArgumentNullException(</code><code>"不包含的指令,指令無效"</code><code>);</code>
<code>100 }</code>
<code>101 CommandMethodActionDelegate cmdaction = commandlist[commandName];</code>
<code>102 </code><code>return</code> <code>cmdaction.Invoke(commandParameter);</code>
<code>103 }</code>
<code>104 }</code>
上面代碼中有說到的HostDevelopment類型,是我定義的一個宿主容器對象,用它來承載指令控制器,以及在這個系列的文章中,都是使用HostDevelopment來進行對控制器的承載,這是後話。現在來看一下HostDevelopment暫時的定義:
<code>1 </code><code>public</code> <code>class</code> <code>CommandParameterCase:ICommandParameter</code>
<code>2 {</code>
<code>3 </code><code>private</code> <code>string</code> <code>_StrText;</code>
<code>4</code>
<code>5 </code><code>public</code> <code>string</code> <code>StrText</code>
<code>6 {</code>
<code>7 </code><code>get</code> <code>{ </code><code>return</code> <code>_StrText; }</code>
<code>8 </code><code>set</code> <code>{ _StrText = value; }</code>
<code>9 }</code>
<code>10 }</code>
<code>1 [Command(</code><code>"MyCommandone"</code><code>)]</code>
<code>2 </code><code>public</code> <code>object</code> <code>test(ICommandParameter commandparameter)</code>
<code>3 {</code>
<code>4 </code><code>if</code> <code>(commandparameter != </code><code>null</code><code>)</code>
<code>5 {</code>
<code>6 CommandParameterCase commandparametercase = commandparameter </code><code>as</code> <code>CommandParameterCase;</code>
<code>7 </code><code>return</code> <code>commandparametercase.StrText;</code>
<code>8 }</code>
<code>9 </code><code>else</code> <code>{ </code><code>return</code> <code>null</code><code>; }</code>
<code>10 }</code>
<code>1 HostDevelopment.Instance.Start();</code>
<code>2 HostDevelopment.Instance.CommandController.RegisterCommand(</code><code>new</code> <code>CommandTest());</code>
<code>3 </code><code>var</code> <code>strtext = HostDevelopment.Instance.Execute(</code><code>"MyCommandone"</code><code>, </code><code>new</code> <code>CommandParameterCase() { StrText = </code><code>"test"</code> <code>});</code>
最後加上對象關系圖解吧,并不是什麼标準的畫法,有助于了解就行了。

END
本文轉自jinyuan0829 51CTO部落格,原文連結:http://blog.51cto.com/jinyuan/1409597,如需轉載請自行聯系原作者