您好,登錄后才能下訂單哦!
小編給大家分享一下C#中擴展命令的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
需求
我還不清楚這種方式是模式還是框架開發中用到的技術,我暫且叫它為命令控制器吧。
命令控制器的主要功能就是獲取用戶提供的命令,然后來執行命令。 在這里我把要執行的“命令”設計成一個函數,會對應著一個String類型的命令字符串,并且命令控制器是允許擴展的。
實現
首先我定義了一個屬性類,用于在擴展的命令類、或者命令函數上,只有一個CommandName屬性,作用于命令函數上的話,則代表命令名稱,如果是作用于類上面的話就代表命令類別的名稱,只是考慮可以作為一個分類,這部分在后面有講到,可以自定義實現。
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 /// 示例:命令類以及命令函數,亦可當作為擴展 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類,而類里面的一些函數的簽名也是一樣的,函數參數都為ICommandParameter接口類型,這就是擴展命令方法時要遵循的一些規范,定義的規范:
1 /// <summary> 2 /// 擴展命令函數的參數規范 3 /// </summary> 4 public interface ICommandParameter 5 { 6 7 } 8 9 /// <summary> 10 /// 擴展命令方法類基類 11 /// </summary> 12 public class CommandMethod 13 { 14 15 }
需要實現什么都是可以自定義,比如說可以在ICommandParameter接口中定義個object類型的名稱為ContainerObject的屬性,意思就是容器屬性,可以在后面調用命令時,傳入實例參數時設置容器屬性的值,可以設置為任何你想設置的值到里面,然后再在命令函數里使用它,也可以根據抽象定義實現一個參數上下文對象專門用于處理擴展命令的,看需要自定義吧。
然后就是書寫一個命令控制器的代碼了,它呢主要負責把客戶端注冊進來的類型做一些處理,比如說 判斷類型、反射類型獲取函數命令以及函數信息、把命令函數轉換成委托、維護命令列表等等一些簡單的功能,還用到了一個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()方法為注冊擴展命令到命令控制器,示例中的注冊方式為手動的傳入類型實例來注冊的,也可以把實現方式修改為在命令控制器啟動的時候獲取當前系統所有依賴項的程序集,獲取到所有符合類型規范的擴展命令類型,并且注冊到控制器中。
上面代碼中有說到的HostDevelopment類型,是我定義的一個宿主容器對象,用它來承載命令控制器,以及在這個系列的文章中,都是使用HostDevelopment來進行對控制器的承載,這是后話。現在來看一下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 }
看了這些了,應該就大致的明白了,不過現在這樣的代碼還是測試不了的,因為缺少一些實體。定義一個默認實現的命令參數規范:
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的函數(對應的命令名稱為MyCommandone),函數名稱有點隨意,大家不要介意這些。
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 }
這樣所需的都定義齊了。 我們再看一下調用代碼:
1 HostDevelopment.Instance.Start(); 2 HostDevelopment.Instance.CommandController.RegisterCommand(new CommandTest()); 3 var strtext = HostDevelopment.Instance.Execute("MyCommandone", new CommandParameterCase() { StrText = "test" });
對了隨便是打個斷點或者是輸出strtext都可以看到它的值。這里不作多的解釋了。
以上是“C#中擴展命令的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。