您好,登錄后才能下訂單哦!
小編給大家分享一下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è)資訊頻道!
免責(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)容。