CommandAdapterFactory.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. 
  2. using System;
  3. using System.Linq;
  4. using System.Reflection;
  5. using System.Reflection.Emit;
  6. using System.Windows.Input;
  7. namespace FWindSoft.MVVM
  8. {
  9. /// <summary>
  10. /// 泛型CommandAdapterFactory类
  11. /// </summary>
  12. /// <typeparam name="T"></typeparam>
  13. internal static class CommandAdapterFactory<T> where T : class
  14. {
  15. private static readonly Type m_Type;
  16. /// <summary>
  17. /// 创建命令适配器(获取Execute方法和CanExecute方法为创建ICommand接口实例准备)
  18. /// </summary>
  19. /// <param name="sender"></param>
  20. /// <returns></returns>
  21. public static object Create(object sender)
  22. {
  23. CommandAdapter inst = (CommandAdapter) m_Type.GetConstructor(new Type[] {}).Invoke(new object[] {});
  24. Type thisType = typeof (T);
  25. MethodInfo[] methods = thisType.GetMethods();
  26. foreach (MethodInfo methodItem in methods)
  27. {
  28. CommandAttribute[] attrs =
  29. methodItem.GetCustomAttributes(typeof (CommandAttribute), true) as CommandAttribute[];
  30. if ((attrs != null) && (attrs.Length != 0))
  31. {
  32. string methodName = methodItem.Name;
  33. string canDoMethodName = "Can" + methodName;
  34. bool hasCanDoMethod = (from method in methods
  35. where method.Name == canDoMethodName
  36. select method).FirstOrDefault() != null;
  37. #region 初始化命令
  38. BaseCommand cmd = new BaseCommand(
  39. (x) =>
  40. {
  41. CommandEventArgs eargs = new CommandEventArgs(inst,
  42. new CommandInfo() { CommandName = methodName });
  43. inst.DoBeforeCommand(eargs);
  44. try
  45. {
  46. try
  47. {
  48. MethodInfo miLocal = thisType.GetMethod(methodName);
  49. ParameterInfo[] pi = miLocal.GetParameters();
  50. if (pi.Length == 0)
  51. {
  52. thisType.InvokeMember(methodName, BindingFlags.Public, null, sender,
  53. new object[] { });
  54. }
  55. else if (pi.Length == 1)
  56. {
  57. thisType.InvokeMember(methodName,
  58. BindingFlags.InvokeMethod, null,
  59. sender, new object[] { x });
  60. }
  61. }
  62. catch
  63. {
  64. throw;
  65. }
  66. }
  67. finally
  68. {
  69. inst.DoAfterCommand(eargs);
  70. }
  71. }, hasCanDoMethod
  72. ? (Predicate<object>)
  73. (
  74. (x) =>
  75. {
  76. return (bool)thisType.InvokeMember(canDoMethodName,
  77. BindingFlags.InvokeMethod, null, sender, new object[] { x });
  78. }
  79. )
  80. : null
  81. );
  82. #endregion
  83. m_Type.InvokeMember(methodItem.Name, BindingFlags.SetProperty, null, inst,
  84. new object[] {cmd});
  85. inst.m_Commands.Add(cmd);
  86. }
  87. }
  88. return inst;
  89. }
  90. /// <summary>
  91. /// 动态创建属性
  92. /// </summary>
  93. static CommandAdapterFactory()
  94. {
  95. try
  96. {
  97. TypeBuilder tb = CodeGenerator.Module.DefineType(typeof (T).Name + "*Commands", TypeAttributes.Class,
  98. typeof (CommandAdapter));
  99. Type thisType = typeof (T);
  100. MethodInfo[] methods = thisType.GetMethods();
  101. foreach (MethodInfo methodItem in methods)
  102. {
  103. CommandAttribute[] attrs =
  104. methodItem.GetCustomAttributes(typeof (CommandAttribute), true) as CommandAttribute[];
  105. if ((attrs != null) && (attrs.Length != 0))
  106. {
  107. FieldBuilder cmdField = tb.DefineField("_" + methodItem.Name, typeof (ICommand),
  108. FieldAttributes.Private);
  109. MethodBuilder cmdGet = tb.DefineMethod("get_" + methodItem.Name, MethodAttributes.Public,
  110. typeof (ICommand), new Type[] {});
  111. ILGenerator cmdGetIL = cmdGet.GetILGenerator();
  112. cmdGetIL.Emit(OpCodes.Ldarg_0);
  113. cmdGetIL.Emit(OpCodes.Ldfld, cmdField);
  114. cmdGetIL.Emit(OpCodes.Ret);
  115. MethodBuilder cmdSet = tb.DefineMethod("set_" + methodItem.Name,
  116. MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName,
  117. typeof (void), new Type[] {typeof (ICommand)});
  118. ILGenerator cmdSetIL = cmdSet.GetILGenerator();
  119. cmdSetIL.Emit(OpCodes.Ldarg_0);
  120. cmdSetIL.Emit(OpCodes.Ldarg_1);
  121. cmdSetIL.Emit(OpCodes.Stfld, cmdField);
  122. cmdSetIL.Emit(OpCodes.Ret);
  123. PropertyBuilder cmdProperty = tb.DefineProperty(methodItem.Name, PropertyAttributes.None,
  124. typeof (ICommand),
  125. new Type[] {});
  126. cmdProperty.SetGetMethod(cmdGet);
  127. cmdProperty.SetSetMethod(cmdSet);
  128. }
  129. }
  130. m_Type = tb.CreateType();
  131. }
  132. catch
  133. {
  134. }
  135. }
  136. }
  137. }