C#中扩展命令的示例分析
小编给大家分享一下C#中扩展命令的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
需求
我还不清楚这种方式是模式还是框架开发中用到的技术,我暂且叫它为命令控制器吧。
命令控制器的主要功能就是获取用户提供的命令,然后来执行命令。 在这里我把要执行的"命令"设计成一个函数,会对应着一个String类型的命令字符串,并且命令控制器是允许扩展的。
实现
首先我定义了一个属性类,用于在扩展的命令类、或者命令函数上,只有一个CommandName属性,作用于命令函数上的话,则代表命令名称,如果是作用于类上面的话就代表命令类别的名称,只是考虑可以作为一个分类,这部分在后面有讲到,可以自定义实现。
1 ///2 /// 命令所用代码属性类3 /// 4 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]5 public class CommandAttribute : Attribute6 {7 private string commandName = null;89 public string CommandName10 {11 get { return commandName; }12 set { commandName = value; }13 }1415 public CommandAttribute(string CommandName)16 {17 commandName = CommandName;18 }19 }
有了这个属性类了,我们就要把它用起来,定义一些后面要用到的命令示例类,
1 ///2 /// 示例:命令类以及命令函数,亦可当作为扩展3 /// 4 [Command("Test")]5 public class CommandTest : CommandMethod6 {7 [Command("MyCommandone")]8 public object test(ICommandParameter commandparameter)9 {10 return null;11 }1213 [Command("MyCommandone1")]14 public object test1(ICommandParameter commandparameter)15 {16 return null;17 }1819 [Command("MyCommandone2")]20 public object test2(ICommandParameter commandparameter)21 {22 return null;23 }242526 [Command("MyCommandone3")]27 public object test3(ICommandParameter commandparameter)28 {29 return null;30 }3132 [Command("MyCommandone4")]33 public object test4(ICommandParameter commandparameter)34 {35 return null;36 }37 }
上面的示例代码中可以看到CommandTest类继承自CommandMethod类,而类里面的一些函数的签名也是一样的,函数参数都为ICommandParameter接口类型,这就是扩展命令方法时要遵循的一些规范,定义的规范:
1 ///2 /// 扩展命令函数的参数规范3 /// 4 public interface ICommandParameter5 {67 }89 ///10 /// 扩展命令方法类基类11 /// 12 public class CommandMethod13 {1415 }
需要实现什么都是可以自定义,比如说可以在ICommandParameter接口中定义个object类型的名称为ContainerObject的属性,意思就是容器属性,可以在后面调用命令时,传入实例参数时设置容器属性的值,可以设置为任何你想设置的值到里面,然后再在命令函数里使用它,也可以根据抽象定义实现一个参数上下文对象专门用于处理扩展命令的,看需要自定义吧。
然后就是书写一个命令控制器的代码了,它呢主要负责把客户端注册进来的类型做一些处理,比如说 判断类型、反射类型获取函数命令以及函数信息、把命令函数转换成委托、维护命令列表等等一些简单的功能,还用到了一个CommandMethodActionDelegate类型的委托:
1 public delegate object CommandMethodActionDelegate(ICommandParameter commandParameter);23 public class CommandController4 {5 private static CommandController _Instance = null;67 public static CommandController Instance8 {9 get10 {11 if (_Instance == null)12 {13 _Instance = new CommandController(HostDevelopment.Instance);14 }15 return _Instance;16 }17 }1819 private HostDevelopment _CommandDevelopment = HostDevelopment.Instance;2021 public CommandController(HostDevelopment commandDevelopment)22 {23 _CommandDevelopment = commandDevelopment;24 }2526 private Dictionarycommandlist = new Dictionary ();272829 private List _commandNames = null;30 /// 31 /// 命令名称集合32 /// 33 public ListCommandNames34 {35 get36 {37 if (_commandNames == null)38 {39 GetCommandNames();40 }41 return _commandNames;42 }43 }4445 private void GetCommandNames()46 {4748 if (commandlist.Count > 0)49 {50 if (_commandNames == null)51 {52 _commandNames = new List ();53 }54 foreach (string name in commandlist.Keys)55 {56 _commandNames.Add(name);57 }58 }59 }6061 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 }7273 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 {8283 CommandMethodActionDelegate commanddelegate = (CommandMethodActionDelegate)Delegate.CreateDelegate(typeof(CommandMethodActionDelegate), instance, methodinfo.Name);84 commandlist.Add(cmdatt.CommandName, commanddelegate);85 }8687 }88 }899091 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);23 public class CommandController4 {5 private static CommandController _Instance = null;67 public static CommandController Instance8 {9 get10 {11 if (_Instance == null)12 {13 _Instance = new CommandController(HostDevelopment.Instance);14 }15 return _Instance;16 }17 }1819 private HostDevelopment _CommandDevelopment = HostDevelopment.Instance;2021 public CommandController(HostDevelopment commandDevelopment)22 {23 _CommandDevelopment = commandDevelopment;24 }2526 private Dictionarycommandlist = new Dictionary ();272829 private List _commandNames = null;30 /// 31 /// 命令名称集合32 /// 33 public ListCommandNames34 {35 get36 {37 if (_commandNames == null)38 {39 GetCommandNames();40 }41 return _commandNames;42 }43 }4445 private void GetCommandNames()46 {4748 if (commandlist.Count > 0)49 {50 if (_commandNames == null)51 {52 _commandNames = new List ();53 }54 foreach (string name in commandlist.Keys)55 {56 _commandNames.Add(name);57 }58 }59 }6061 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 }7273 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 {8283 CommandMethodActionDelegate commanddelegate = (CommandMethodActionDelegate)Delegate.CreateDelegate(typeof(CommandMethodActionDelegate), instance, methodinfo.Name);84 commandlist.Add(cmdatt.CommandName, commanddelegate);85 }8687 }88 }899091 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:ICommandParameter2 {3 private string _StrText;45 public string StrText6 {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#中扩展命令的示例分析"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!