溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

C#中擴(kuò)展命令的示例分析

發(fā)布時間:2021-10-21 13:45:09 來源:億速云 閱讀:123 作者:小新 欄目:編程語言

小編給大家分享一下C#中擴(kuò)展命令的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

需求

我還不清楚這種方式是模式還是框架開發(fā)中用到的技術(shù),我暫且叫它為命令控制器吧。

命令控制器的主要功能就是獲取用戶提供的命令,然后來執(zhí)行命令。 在這里我把要執(zhí)行的“命令”設(shè)計成一個函數(shù),會對應(yīng)著一個String類型的命令字符串,并且命令控制器是允許擴(kuò)展的。

實現(xiàn)
首先我定義了一個屬性類,用于在擴(kuò)展的命令類、或者命令函數(shù)上,只有一個CommandName屬性,作用于命令函數(shù)上的話,則代表命令名稱,如果是作用于類上面的話就代表命令類別的名稱,只是考慮可以作為一個分類,這部分在后面有講到,可以自定義實現(xiàn)。

1     /// <summary>
2     /// 命令所用代碼屬性類
3     /// </summary>
4     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
5     public class CommandAttribute : Attribute
6     {
7         private string commandName = null;
8
9         public string CommandName
10         {
11             get { return commandName; }
12             set { commandName = value; }
13         }
14
15         public CommandAttribute(string CommandName)
16         {
17             commandName = CommandName;
18         }
19     }

有了這個屬性類了,我們就要把它用起來,定義一些后面要用到的命令示例類,

1     /// <summary>
2     /// 示例:命令類以及命令函數(shù),亦可當(dāng)作為擴(kuò)展
3     /// </summary>
4     [Command("Test")]
5     public class CommandTest : CommandMethod
6     {
7         [Command("MyCommandone")]
8         public object test(ICommandParameter commandparameter)
9         {
10             return null;
11         }
12
13         [Command("MyCommandone1")]
14         public object test1(ICommandParameter commandparameter)
15         {
16             return null;
17         }
18
19         [Command("MyCommandone2")]
20         public object test2(ICommandParameter commandparameter)
21         {
22             return null;
23         }
24
25
26         [Command("MyCommandone3")]
27         public object test3(ICommandParameter commandparameter)
28         {
29             return null;
30         }
31
32         [Command("MyCommandone4")]
33         public object test4(ICommandParameter commandparameter)
34         {
35             return null;
36         }
37     }

上面的示例代碼中可以看到CommandTest類繼承自CommandMethod類,而類里面的一些函數(shù)的簽名也是一樣的,函數(shù)參數(shù)都為ICommandParameter接口類型,這就是擴(kuò)展命令方法時要遵循的一些規(guī)范,定義的規(guī)范:

1     /// <summary>
2     /// 擴(kuò)展命令函數(shù)的參數(shù)規(guī)范
3     /// </summary>
4     public interface ICommandParameter
5     {
6
7     }
8
9     /// <summary>
10     /// 擴(kuò)展命令方法類基類
11     /// </summary>
12     public class CommandMethod
13     {
14
15     }

需要實現(xiàn)什么都是可以自定義,比如說可以在ICommandParameter接口中定義個object類型的名稱為ContainerObject的屬性,意思就是容器屬性,可以在后面調(diào)用命令時,傳入實例參數(shù)時設(shè)置容器屬性的值,可以設(shè)置為任何你想設(shè)置的值到里面,然后再在命令函數(shù)里使用它,也可以根據(jù)抽象定義實現(xiàn)一個參數(shù)上下文對象專門用于處理擴(kuò)展命令的,看需要自定義吧。

然后就是書寫一個命令控制器的代碼了,它呢主要負(fù)責(zé)把客戶端注冊進(jìn)來的類型做一些處理,比如說 判斷類型、反射類型獲取函數(shù)命令以及函數(shù)信息、把命令函數(shù)轉(zhuǎn)換成委托、維護(hù)命令列表等等一些簡單的功能,還用到了一個CommandMethodActionDelegate類型的委托:

1     public delegate object CommandMethodActionDelegate(ICommandParameter commandParameter);
2
3     public class CommandController
4     {
5         private static CommandController _Instance = null;
6
7         public static CommandController Instance
8         {
9             get
10             {
11                 if (_Instance == null)
12                 {
13                     _Instance = new CommandController(HostDevelopment.Instance);
14                 }
15                 return _Instance;
16             }
17         }
18
19         private HostDevelopment _CommandDevelopment = HostDevelopment.Instance;
20
21         public CommandController(HostDevelopment commandDevelopment)
22         {
23             _CommandDevelopment = commandDevelopment;
24         }
25
26         private Dictionary<string, CommandMethodActionDelegate> commandlist = new Dictionary<string, CommandMethodActionDelegate>();
27
28
29         private List<string> _commandNames = null;
30         /// <summary>
31         /// 命令名稱集合
32         /// </summary>
33         public List<string> CommandNames
34         {
35             get
36             {
37                 if (_commandNames == null)
38                 {
39                     GetCommandNames();
40                 }
41                 return _commandNames;
42             }
43         }
44
45         private void GetCommandNames()
46         {
47
48             if (commandlist.Count > 0)
49             {
50                 if (_commandNames == null)
51                 {
52                     _commandNames = new List<string>();
53                 }
54                 foreach (string name in commandlist.Keys)
55                 {
56                     _commandNames.Add(name);
57                 }
58             }
59         }
60
61         public bool RegisterCommand(object instance)
62         {
63             Type t = instance.GetType();
64             CommandAttribute cmdatt = (CommandAttribute)Attribute.GetCustomAttribute(t, typeof(CommandAttribute), false);
65             if (cmdatt != null)
66             {
67                 AddCommandToModel(instance);
68                 return true;
69             }
70             else { return false; }
71         }
72
73         private void AddCommandToModel(object instance)
74         {
75             Type t = instance.GetType();
76             MethodInfo[] methods = t.GetMethods();
77             foreach (MethodInfo methodinfo in methods)
78             {
79                 CommandAttribute cmdatt = (CommandAttribute)Attribute.GetCustomAttribute(methodinfo, typeof(CommandAttribute), false);
80                 if (cmdatt != null)
81                 {
82
83                     CommandMethodActionDelegate commanddelegate = (CommandMethodActionDelegate)Delegate.CreateDelegate(typeof(CommandMethodActionDelegate), instance, methodinfo.Name);
84                     commandlist.Add(cmdatt.CommandName, commanddelegate);
85                 }
86
87             }
88         }
89
90
91         internal object Execute(string commandName, ICommandParameter commandParameter)
92         {
93             if (commandName == null)
94             {
95                 throw new ArgumentNullException("commandName");
96             }
97             if (!commandlist.ContainsKey(commandName))
98             {
99                 return new ArgumentNullException("不包含的命令,命令無效");
100             }
101             CommandMethodActionDelegate cmdaction = commandlist[commandName];
102             return cmdaction.Invoke(commandParameter);
103         }
104     }
在CommandController類型中,RegisterCommand()方法為注冊擴(kuò)展命令到命令控制器,示例中的注冊方式為手動的傳入類型實例來注冊的,也可以把實現(xiàn)方式修改為在命令控制器啟動的時候獲取當(dāng)前系統(tǒng)所有依賴項的程序集,獲取到所有符合類型規(guī)范的擴(kuò)展命令類型,并且注冊到控制器中。

上面代碼中有說到的HostDevelopment類型,是我定義的一個宿主容器對象,用它來承載命令控制器,以及在這個系列的文章中,都是使用HostDevelopment來進(jìn)行對控制器的承載,這是后話?,F(xiàn)在來看一下HostDevelopment暫時的定義:

1     public delegate object CommandMethodActionDelegate(ICommandParameter commandParameter);
2
3     public class CommandController
4     {
5         private static CommandController _Instance = null;
6
7         public static CommandController Instance
8         {
9             get
10             {
11                 if (_Instance == null)
12                 {
13                     _Instance = new CommandController(HostDevelopment.Instance);
14                 }
15                 return _Instance;
16             }
17         }
18
19         private HostDevelopment _CommandDevelopment = HostDevelopment.Instance;
20
21         public CommandController(HostDevelopment commandDevelopment)
22         {
23             _CommandDevelopment = commandDevelopment;
24         }
25
26         private Dictionary<string, CommandMethodActionDelegate> commandlist = new Dictionary<string, CommandMethodActionDelegate>();
27
28
29         private List<string> _commandNames = null;
30         /// <summary>
31         /// 命令名稱集合
32         /// </summary>
33         public List<string> CommandNames
34         {
35             get
36             {
37                 if (_commandNames == null)
38                 {
39                     GetCommandNames();
40                 }
41                 return _commandNames;
42             }
43         }
44
45         private void GetCommandNames()
46         {
47
48             if (commandlist.Count > 0)
49             {
50                 if (_commandNames == null)
51                 {
52                     _commandNames = new List<string>();
53                 }
54                 foreach (string name in commandlist.Keys)
55                 {
56                     _commandNames.Add(name);
57                 }
58             }
59         }
60
61         public bool RegisterCommand(object instance)
62         {
63             Type t = instance.GetType();
64             CommandAttribute cmdatt = (CommandAttribute)Attribute.GetCustomAttribute(t, typeof(CommandAttribute), false);
65             if (cmdatt != null)
66             {
67                 AddCommandToModel(instance);
68                 return true;
69             }
70             else { return false; }
71         }
72
73         private void AddCommandToModel(object instance)
74         {
75             Type t = instance.GetType();
76             MethodInfo[] methods = t.GetMethods();
77             foreach (MethodInfo methodinfo in methods)
78             {
79                 CommandAttribute cmdatt = (CommandAttribute)Attribute.GetCustomAttribute(methodinfo, typeof(CommandAttribute), false);
80                 if (cmdatt != null)
81                 {
82
83                     CommandMethodActionDelegate commanddelegate = (CommandMethodActionDelegate)Delegate.CreateDelegate(typeof(CommandMethodActionDelegate), instance, methodinfo.Name);
84                     commandlist.Add(cmdatt.CommandName, commanddelegate);
85                 }
86
87             }
88         }
89
90
91         internal object Execute(string commandName, ICommandParameter commandParameter)
92         {
93             if (commandName == null)
94             {
95                 throw new ArgumentNullException("commandName");
96             }
97             if (!commandlist.ContainsKey(commandName))
98             {
99                 return new ArgumentNullException("不包含的命令,命令無效");
100             }
101             CommandMethodActionDelegate cmdaction = commandlist[commandName];
102             return cmdaction.Invoke(commandParameter);
103         }
104     }
看了這些了,應(yīng)該就大致的明白了,不過現(xiàn)在這樣的代碼還是測試不了的,因為缺少一些實體。定義一個默認(rèn)實現(xiàn)的命令參數(shù)規(guī)范:
1     public class CommandParameterCase:ICommandParameter
2     {
3         private string _StrText;
4
5         public string StrText
6         {
7             get { return _StrText; }
8             set { _StrText = value; }
9         }
10     }
然后再修改一下CommandTest類型中的第一個叫test的函數(shù)(對應(yīng)的命令名稱為MyCommandone),函數(shù)名稱有點隨意,大家不要介意這些。
1         [Command("MyCommandone")]
2         public object test(ICommandParameter commandparameter)
3         {
4             if (commandparameter != null)
5             {
6                 CommandParameterCase commandparametercase = commandparameter as CommandParameterCase;
7                 return commandparametercase.StrText;
8             }
9             else { return null; }
10         }
這樣所需的都定義齊了。
我們再看一下調(diào)用代碼:
1 HostDevelopment.Instance.Start();
2 HostDevelopment.Instance.CommandController.RegisterCommand(new CommandTest());
3 var strtext = HostDevelopment.Instance.Execute("MyCommandone", new CommandParameterCase() { StrText = "test" });
對了隨便是打個斷點或者是輸出strtext都可以看到它的值。這里不作多的解釋了。

以上是“C#中擴(kuò)展命令的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI